Frictional Games Forum (read-only)

Full Version: [SOLVED] Using a Single Crowbar on Multiple Doors
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2 3 4 5
All righty, so basically I'm trying to break against the traditional crowbar-breaks-after-one-use shenanigans and I have at least four doors that will require using the crowbar, three being the regular mansion door and the last being boards covering a door.

I've been able to successfully script for a single door, but now that I have to add to it, I have no idea where to really start. While I know that I can use the Variables to help condense the scripts, I'm not entirely sure how to go about it or if with also needing to script for boards, if that might makes things a little different.

____________________________________________________________
Finished Script:

-Be sure to check the names thoroughly
-I'm leaving the 4 in the script, but you do not necessarily have to leave it at 4

Thank you to the guys who contributed to this thread to get this script working![/code]

Code:
void OnStart()
{  
    for(int i = 1; i <= 4; i++) {
    AddUseItemCallback("crowbarondoors", "crowbar", "Door_"+i, "UseCrowbarOnDoor", false);
    AddEntityCollideCallback("Joint_Door_"+i, "AreaBreak_"+i, "BreakDoor", true, 1);
    }
}
    
void UseCrowbarOnDoor(string &in asItem, string &in asEntity)
{
    RemoveItem(asItem);
    PlaySoundAtEntity("", "player_crouch.snt", "Player", 0.05, false);
    AddTimer(asEntity, 0.2, "TimerPlaceCrowbar");

    SetLocalVarString("CrowbarDoor", asEntity);
}
    
void TimerPlaceCrowbar(string &in asTimer)
{
    SetEntityActive("Joint_"+asTimer, true);
    PlaySoundAtEntity("", "puzzle_place_jar.snt", asTimer, 0, false);
}
    
void BreakDoor(string &in asParent, string &in asChild, int alState)
{
    SetEntityActive(asParent, false);
  
    SetSwingDoorLocked(GetLocalVarString("CrowbarDoor"), false, false);
    SetSwingDoorClosed(GetLocalVarString("CrowbarDoor"), false, false);
    SetSwingDoorDisableAutoClose(GetLocalVarString("CrowbarDoor"), true);
    
    AddPropImpulse(GetLocalVarString("CrowbarDoor"), 0, 0, 3, "world");

    CreateParticleSystemAtEntity("", "ps_hit_wood.ps", "AreaEffect_"+asChild, false);
    PlaySoundAtEntity("", "break_wood_metal", "AreaEffect_"+asChild, 0, false);
    
    GiveSanityBoostSmall();
    
    PlayMusic("10_puzzle01.ogg", false, 0.7, 0.1, 10, false);
    
    AddTimer("", 0.1, "TimerPushDoor");

    GiveItem("crowbar", "Puzzle", "crowbar", "crowbar.tga", 1);
}

void TimerPushDoor(string &in asTimer)
{
        AddPropImpulse(GetLocalVarString("CrowbarDoor"), -4, 2, 1, "world");
        AddTimer("", 1.1, "TimerDoorCanClose");
}
    
void TimerDoorCanClose(string &in asTimer)
{
        SetSwingDoorDisableAutoClose(GetLocalVarString("CrowbarDoor"), false);
}
You can try to check what entity the crowbar is being used at.

Code:
if(asEntity == "NameOfDoor")
{
     //Setup the stuff you want to happen for this door
}
else if(asEntity == "ThisNameOfDoor")
{
     //Setup the other door here
}

Basically, you do all four doors in one single use item script.
At least I hope this is what youre looking for.
Yeah, that's basically what I'm looking for, to be able to use the one item for all four functions, but I'm not entirely sure how to use the script you posted.
I'd suggest writing a script without the usage of normal names, but with asEntity and asItem instead. That way you can use the same thing few times. I'm not sure if it's possible thouh, haven't done that.

PS. I'm proud of ya for not breaking the crowbar in half. It's such a crap Tongue
Basically you write a regular use item function and put all these things in there. Here's a breef example.

Code:
void UseCrowbarOnDoor(string &in asEntity, string &in asItem)
{
      if(asEntity == "mansion_1")
      {
           SetPropHealth(asEntity); //Break the door (for some reason)
      }
      else if(asEntity == "mansion_2")
      {
           SetEntityActive("crowbar", true); //Some simple activate entity
      }
}

void OnStart()
{
     for(int i=1; i<=4; ++i) AddUseItemCallback("crowbarondoors", "crowbar", "mansion_"+i, "UseCrowbarOnDoor", false);
}

Go ahead and ask me if theres anything you don't entirely understand about the script.
Oh! I think I get what you mean!! (Not gonna lie, that makes me feel super awesome since I'm still learning the craft of scripting).

I'll test it out and let you know how it goes.

_____________________________________________________________
EDIT:

I don't think I'm doing this correctly. This is the script that I'm running on a test map (to prevent any unsavory things from happening to the rest of the script file).

There are probably some other errors in here as I had previously used this to run another test and I don't think I quite found all the leftovers of that.

Code:
void OnStart()
{  
    AddUseItemCallback("", "Crowbar_1", "asEntity", "UseCrowbarOnDoor", true);
    AddEntityCollideCallback("Joint", "AreaBreak", "BreakDoor", true, 1);
}
    
void UseCrowbarOnDoor(string &in asItem, string &in asEntity)
{
    if(asEntity == "Door_1")
      {
        PlaySoundAtEntity("", "player_crouch.snt", "Player", 0.05, false);
        AddTimer(asEntity, 0.2, "TimerPlaceCrowbar");
      }
      else if(asEntity == "Door_2")
      {
        PlaySoundAtEntity("", "player_crouch.snt", "Player", 0.05, false);
        AddTimer(asEntity, 0.2, "TimerPlaceCrowbar");
      }
}
    
void TimerPlaceCrowbar(string &in asTimer)
{
        SetEntityActive("Joint", true);
        PlaySoundAtEntity("", "puzzle_place_jar.snt", asTimer, 0, false);
}
    
void BreakDoor(string &in asParent, string &in asChild, int alState)
{
        SetEntityActive("Joint", false);
        SetEntityActive("Broken", true);
  
        SetSwingDoorLocked("Door_x", false, false);
        SetSwingDoorClosed("Door_x", false, false);
        SetSwingDoorDisableAutoClose("Door_x", true);
    
        AddPropImpulse("Door_x", 0, 0, 3, "world");
    
        CreateParticleSystemAtEntity("", "ps_hit_wood.ps", "AreaEffect", false);
        PlaySoundAtEntity("", "break_wood_metal", "AreaEffect", 0, false);
    
        GiveSanityBoostSmall();
    
        PlayMusic("10_puzzle01.ogg", false, 0.7, 0.1, 10, false);
    
        AddTimer("", 0.1, "TimerPushDoor");
}
    
void TimerPushDoor(string &in asTimer)
{
        AddPropImpulse("Door_x", -4, 2, 1, "world");
        AddTimer("", 1.1, "TimerDoorCanClose");
}
    
void TimerDoorCanClose(string &in asTimer)
{
        SetSwingDoorDisableAutoClose("Door_x", false);
}
You're getting closer but not all the way.

I'm very sorry about this but
WALL OF TEXT INCOMING!
I felt inspired to help you ^^

See, in the beginning you wrote:

PHP Code:
void OnStart()
{  
    
AddUseItemCallback("""Crowbar_1""asEntity""UseCrowbarOnDoor"true);
    
AddEntityCollideCallback("Joint""AreaBreak""BreakDoor"true1);


You used "asEntity" as the entity. This will not work, and there's a simple explanation.

asEntity, is referring to the parameters in a function.
Fx. when using a collide-function you write:

void CollideFunction(string &in asParent, string &in asChild, int alState)

Notice all the things inside the paranthesises! ^^^^^
You have 3 different parameters here: asParent, asChild and alState.
asParent and asChild has "string" in front of them, because you have to use a word.
alState has "int" in front of it, because it's a whole number, without decimals (1, 0, or -1)

But you wrote "asEntity" in voidOnStart(), which has nothing in the paranthesises. That's why it won't work.

Neelke wrote this:
PHP Code:
void OnStart()
{
for(
int i=1i<=4; ++iAddUseItemCallback("crowbarondoors""crowbar""mansion_"+i"UseCrowbarOnDoor"false);


for(int i=1; i<=4; ++i) is used to create a loop.
The first number "int i=1;" says that it has to start at 1.
The second number "i<=4;" says that it has to end at 4.

So by writing "mansion_"+i in the entities-space he selects all the mansion doors named, mansion_1, mansion_2, mansion_3, and mansion_4.

He did this, to save time and space. To understand it better, what he's actually doing is writing this:
PHP Code:
void OnStart()
{
AddUseItemCallback("crowbarondoors""crowbar""mansion_1""UseCrowbarOnDoor"false);
AddUseItemCallback("crowbarondoors""crowbar""mansion_2""UseCrowbarOnDoor"false);
AddUseItemCallback("crowbarondoors""crowbar""mansion_3""UseCrowbarOnDoor"false);
AddUseItemCallback("crowbarondoors""crowbar""mansion_4""UseCrowbarOnDoor"false);


Do you see?
He selects all the doors, but he uses the same crowbar. This means that the function "UseCrowbarOnDoor" will call when he uses "crowbar" on either of the selected doors.

In your script, you have chosen to name all the doors "Door_1", "Door_2", and so on...
Remember to rename these.

Now to the function.

PHP Code:
void UseCrowbarOnDoor(string &in asItemstring &in asEntity)
{
    if(
asEntity == "Door_1")
      {
        
PlaySoundAtEntity("""player_crouch.snt""Player"0.05false);
        
AddTimer(asEntity0.2"TimerPlaceCrowbar");
      }
      else if(
asEntity == "Door_2")
      {
        
PlaySoundAtEntity("""player_crouch.snt""Player"0.05false);
        
AddTimer(asEntity0.2"TimerPlaceCrowbar");
      }


In this function you are only checking for 2 of the doors. If i recall correctly, you had 4. So the script is not done before you've done it to all 4 doors.
BUT! Since you are now learning about "asEntity" how about we optimize the script a bit?

PHP Code:
void UseCrowbarOnDoor(string &in asItemstring &in asEntity)
{
RemoveItem("asItem");
PlaySoundAtEntity("""player_crouch.snt""Player"0.05false);
AddTimer(asEntity0.2"TimerPlaceCrowbar");

SetLocalVarString("CrowbarDoor"asEntity);


Since you are using "asEntity" in the AddTimer it doesn't matter which door you are using it on, since it will always pick the door you are using it on anyway. (Because the door you are using the crowbar on will automatically be "asEntity").

Notice that I added an extra line about setting a "string" to asEntity. This will be useful later. I'm just storing the information. Just read along.

Also notice that I'm removing the crowbar. This is so that the player won't go and use the crowbar on another area, while the joint it active, because then suddenly 2 joints will be active, meaning 2 crowbars. And the player will be like: "Wut? How did i do that?"

Now something a little more difficult appears.

PHP Code:
void TimerPlaceCrowbar(string &in asTimer)
{
        
SetEntityActive("Joint"true);
        
PlaySoundAtEntity("""puzzle_place_jar.snt"asTimer0false);


You have chosen only to set "Joint" active. Since there's only 1 object named "Joint" in the map, and it's only placed at 1 of the doors, what will happen at the 4 other doors?
Good question. Right now, the answer is: The same "Joint" will go active again. Which is, (what I'm pretty sure) not what you want.

So instead, let's go and rename all the "Joints" into "Joint_Door_1" if it's at "Door_1", "Joint_Door_2" if it's at "Door_2". And so on...
Hopefully you get the idea now.

This means that we can now write:

PHP Code:
void TimerPlaceCrowbar(string &in asTimer)
{
        
SetEntityActive("Joint_"+asTimertrue);
        
PlaySoundAtEntity("""puzzle_place_jar.snt"asTimer0false);


This is because "asTimer" was previously set to be "asEntity", which was the door we were using the crowbar on, in the first case: "Door_1". This means that the object that goes active is "Joint_Door_1", just as we renamed it to.

So what happens when the Joint collides with the area?

PHP Code:
void BreakDoor(string &in asParentstring &in asChildint alState)
{
        
SetEntityActive("Joint"false);
        
SetEntityActive("Broken"true);
  
        
SetSwingDoorLocked("Door_x"falsefalse);
        
SetSwingDoorClosed("Door_x"falsefalse);
        
SetSwingDoorDisableAutoClose("Door_x"true);
    
        
AddPropImpulse("Door_x"003"world");
    
        
CreateParticleSystemAtEntity("""ps_hit_wood.ps""AreaEffect"false);
        
PlaySoundAtEntity("""break_wood_metal""AreaEffect"0false);
     
        
GiveSanityBoostSmall();
     
        
PlayMusic("10_puzzle01.ogg"false0.70.110false);
     
        
AddTimer(""0.1"TimerPushDoor");


This is not general enough, since the exact same thing will happen, as the above where, only the first Joint will be deactivated.
So let's touch it up a bit:

PHP Code:
void BreakDoor(string &in asParentstring &in asChildint alState)
{
        
SetEntityActive(asParentfalse);
  
        
SetSwingDoorLocked(GetLocalVarString("CrowbarDoor"), falsefalse);
        
SetSwingDoorClosed(GetLocalVarString("CrowbarDoor"), falsefalse);
        
SetSwingDoorDisableAutoClose(GetLocalVarString("CrowbarDoor"), true);
    
        
AddPropImpulse(GetLocalVarString("CrowbarDoor"), 003"world");
    
        
CreateParticleSystemAtEntity("""ps_hit_wood.ps""AreaEffect"false);
        
PlaySoundAtEntity("""break_wood_metal""AreaEffect"0false);
     
        
GiveSanityBoostSmall();
     
        
PlayMusic("10_puzzle01.ogg"false0.70.110false);
     
        
AddTimer(""0.1"TimerPushDoor");

GiveItem("crowbar""Puzzle""crowbar""crowbar.tga"1);


Ok, so what did I edit?

I changed the SetEntityActive entity to asParent, because now we're just setting the Joint inactive.
And now you wanted to add a broken crowbar? Why is that exactly? Because since you're going to be using it again, it shouldn't just break should it?
I deleted that line.

And here comes the special thing. I'm now pulling back the information I stored earlier by using GetLocalVarString("CrowbarDoor"). This way, it'll remember what door it was we were using it on, because it we set it that way.

Also, notice that in the end I'm giving the player the crowbar again, so that he can use it again.

This became rather long. I hope you understand! Smile


EDIT:
Oh right. And in the last 2 functions:

PHP Code:
void TimerPushDoor(string &in asTimer)
{
        
AddPropImpulse("Door_x", -421"world");
        
AddTimer(""1.1"TimerDoorCanClose");
}
     
void TimerDoorCanClose(string &in asTimer)
{
        
SetSwingDoorDisableAutoClose("Door_x"false);


Just put "GetLocalVarString("CrowbarDoor")" instead of "Door_x", because "Door_x" isn't anything you have in the editor, and therefore nothing will happen.

It will look like this:

PHP Code:
void TimerPushDoor(string &in asTimer)
{
        
AddPropImpulse(GetLocalVarString("CrowbarDoor"), -421"world");
        
AddTimer(""1.1"TimerDoorCanClose");
}
     
void TimerDoorCanClose(string &in asTimer)
{
        
SetSwingDoorDisableAutoClose(GetLocalVarString("CrowbarDoor"), false);

Oh my goodness, Flawless!! Thank you so much! I knew something needed to happen with the +i, but thought it was the _x (facepalm). And it all made complete sense to me, so thank you thank you thank you!

Unfortunately though, I'm trying to run this on my test map, and I can't even use the crowbar on the door. I'm wondering if maybe some of the names don't match up, but this has become such a scrambled mess in my own head, I'm probably just looking it right over.

Here is the revised .hps:

Spoiler below!
Code:
void OnStart()
{  
    for(int i=1; i<=4; ++i) AddUseItemCallback("crowbarondoors", "crowbar", "mansion_"+i, "UseCrowbarOnDoor", false);
    AddEntityCollideCallback("Joint", "AreaBreak", "BreakDoor", true, 1);
}
    
void UseCrowbarOnDoor(string &in asItem, string &in asEntity)
{
    RemoveItem("asItem");
    PlaySoundAtEntity("", "player_crouch.snt", "Player", 0.05, false);
    AddTimer(asEntity, 0.2, "TimerPlaceCrowbar");

SetLocalVarString("CrowbarDoor", asEntity);
}
    
void TimerPlaceCrowbar(string &in asTimer)
{
        SetEntityActive("Joint_"+asTimer, true);
        PlaySoundAtEntity("", "puzzle_place_jar.snt", asTimer, 0, false);
}
    
void BreakDoor(string &in asParent, string &in asChild, int alState)
{
        SetEntityActive(asParent, false);
  
        SetSwingDoorLocked(GetLocalVarString("CrowbarDoor"), false, false);
        SetSwingDoorClosed(GetLocalVarString("CrowbarDoor"), false, false);
        SetSwingDoorDisableAutoClose(GetLocalVarString("CrowbarDoor"), true);
    
        AddPropImpulse(GetLocalVarString("CrowbarDoor"), 0, 0, 3, "world");
    
        CreateParticleSystemAtEntity("", "ps_hit_wood.ps", "AreaEffect", false);
        PlaySoundAtEntity("", "break_wood_metal", "AreaEffect", 0, false);
    
        GiveSanityBoostSmall();
    
        PlayMusic("10_puzzle01.ogg", false, 0.7, 0.1, 10, false);
    
        AddTimer("", 0.1, "TimerPushDoor");

GiveItem("crowbar", "Puzzle", "crowbar", "crowbar.tga", 1);
}

void TimerPushDoor(string &in asTimer)
{
        AddPropImpulse(GetLocalVarString("CrowbarDoor"), -4, 2, 1, "world");
        AddTimer("", 1.1, "TimerDoorCanClose");
}
    
void TimerDoorCanClose(string &in asTimer)
{
        SetSwingDoorDisableAutoClose(GetLocalVarString("CrowbarDoor"), false);
}


And here are the assets we are starting out with:

Crowbar: Crowbar_1
Door: Door_1
Joint: Joint_Door_1
Areas: AreaBreak_1 (for where the joint hits to call the script)
AreaEffect_1 (for the particles as the door opens)

So the question I have is: do I need to do the same variable technique for the areas as well? Is there anything else that I am missing?


________________________________________________________________
EDIT:

Nvm! I realized that some of the more obvious names were not changed!

Now, the crowbar is not showing up after using the crowbar on the door. The sounds is played, but there is no crowbar!

Revised script is as so:

Spoiler below!
Code:
void OnStart()
{  
    for(int i=1; i<=4; ++i) AddUseItemCallback("crowbarondoors", "Crowbar_1", "Door_"+i, "UseCrowbarOnDoor", false);
    for(int i=1; i<=4; ++i) AddEntityCollideCallback("Joint_Door_"+i, "AreaBreak_"+i, "BreakDoor", true, 1);
}
    
void UseCrowbarOnDoor(string &in asItem, string &in asEntity)
{
    RemoveItem("asItem");
    PlaySoundAtEntity("", "player_crouch.snt", "Player", 0.05, false);
    AddTimer(asEntity, 0.2, "TimerPlaceCrowbar");

    SetLocalVarString("CrowbarDoor", asEntity);
}
    
void TimerPlaceCrowbar(string &in asTimer)
{
    SetEntityActive("Joint_Door_"+asTimer, true);
    PlaySoundAtEntity("", "puzzle_place_jar.snt", asTimer, 0, false);
}
    
void BreakDoor(string &in asParent, string &in asChild, int alState)
{
    SetEntityActive(asParent, false);
  
    SetSwingDoorLocked(GetLocalVarString("CrowbarDoor"), false, false);
    SetSwingDoorClosed(GetLocalVarString("CrowbarDoor"), false, false);
    SetSwingDoorDisableAutoClose(GetLocalVarString("CrowbarDoor"), true);
    
    AddPropImpulse(GetLocalVarString("CrowbarDoor"), 0, 0, 3, "world");

    CreateParticleSystemAtEntity("", "ps_hit_wood.ps", "AreaEffect", false);
    PlaySoundAtEntity("", "break_wood_metal", "AreaEffect", 0, false);
    
    GiveSanityBoostSmall();
    
    PlayMusic("10_puzzle01.ogg", false, 0.7, 0.1, 10, false);
    
    AddTimer("", 0.1, "TimerPushDoor");

    GiveItem("crowbar", "Puzzle", "crowbar", "crowbar.tga", 1);
}

void TimerPushDoor(string &in asTimer)
{
        AddPropImpulse(GetLocalVarString("CrowbarDoor"), -4, 2, 1, "world");
        AddTimer("", 1.1, "TimerDoorCanClose");
}
    
void TimerDoorCanClose(string &in asTimer)
{
        SetSwingDoorDisableAutoClose(GetLocalVarString("CrowbarDoor"), false);
}

On your SetEntityActive line within TimerPlaceCrowbar, try doing "Joint_"+asTimer instead. If your joint name is Joint_Door_1 and asTimer is the same as your door name, then doing what you have will result in Joint_Door_Door_1.

Just trace it back if you're unsure. asTimer = internal name from the AddTimer function calling, which is a few lines above. That internal name = asEntity of the UseCrowbarOnDoor function. asEntity in the function creating that callback is "Door_"+i, so "Door_1" for example, depending on the door.
That fixed the crowbar appearing. Now all it does is go back and forth. The door is not breaking.
Pages: 1 2 3 4 5