New To Scripting - Help With Shootable Triggers?

broken avatar :(
Created 1108 days ago
by kingneo
0 Members and 1 Guest are viewing this topic.
2,046 views
broken avatar :(
×
broken avatar :(
Location: us
Date Registered: 13 July 2016
Last active: 1054 days ago
Posts
17
Respect
Forum Rank
Legless Crawler
Primary Group
Member
×
kingneo's Groups
kingneo's Contact & Social Links
Hi guys,

I'm very new to scripting and the mod tools in general. I have gotten a map somewhat developed and I think I want to start adding some Easter Egg stuff. What I am trying to do right now is have it so that when the player shoots the three teddy bears that I have around the map, they are given the Electric Cherry perk. I could have this just be another buyable perk, which is what I currently have, but I kind of want it to be an easter egg type thing.

Any ideas on how I would go about achieving this? Again, very new to scripting and the mod tools, so please try to be as specific as possible and try to talk like you would to a child :D
broken avatar :(
×
broken avatar :(
Location: gb
Date Registered: 4 October 2016
Last active: 1037 days ago
Posts
10
Respect
Forum Rank
Legless Crawler
Primary Group
Member
×
Xylozi's Groups
Xylozi's Contact & Social Links
This should be pretty simple for you to implement. What you'll need to do is setup some trigger_damage brushes around the teddy bear models and monitor when players shoot them.

Here is code that will do that for you:

In the main function add:
callback::on_spawned( &on_player_spawned );
This will allow you to use on_player_spawned within your file.

And this, which checks your map for any triggers with the "teddy_trigger" targetname and sets up the logic for them:
level.teddy_triggers = getEntArray( "teddy_trigger", "targetname" );
    if( isDefined( level.teddy_triggers ) )
    {
        id = 0;
        foreach( trigger in level.teddy_triggers )
        {
            trigger thread teddy_think(id);
            id++;
        }
    }

Add the on_player_spawned function. This sets a variable to monitor how many teddies the player has shot, and ties the not shot/shot state to the player, meaning progress towards the perk is personal for each player.
function on_player_spawned()
{
    self notify( "teddy_check" );
   
    self.teddy_triggered_count = 0;
   
    // Used so multiple players can do the process, rather than tying progress to the teddies
    self.teddy_states = [];
    for( i = 0; i < level.teddy_triggers.size; i++ )
    {
        self.teddy_states[i] = false;
    }
}

Add the logic for the teddy triggers:
function teddy_think( id )
{
    while(1)
    {
        self waittill( "damage", amount, attacker, directionVec, point, type );
       
        if( !IsDefined( attacker ) || !IsPlayer( attacker ) )
{
WAIT_SERVER_FRAME;
continue;
}
       
        if( IsPlayer( attacker ) )
        {
            if( IsDefined( attacker.teddy_states ) && attacker.teddy_states[id] == false )
            {
                attacker.teddy_states[id] = true;
                attacker thread checkTeddyProgress();
            }
        }
    }
}
This monitors the trigger for any damage events, and once one happens, checks that it comes from player. If the player hasn't shot the teddy before, it will set that teddy to true for the player, and check the player's progress.

Add the checkTeddyProgress function:
function checkTeddyProgress()
{
    count = 0;
    foreach( entry in self.teddy_states )
    {
        if( entry == true )
        {
            count++;
        }
    }
   
    // They have hit every teddy
    if( count >= level.teddy_triggers.size )
    {
        self _zm_perks::give_perk( "marathon_perk" );
    }
}
This is called when the player hits any of the teddies, so once they've hit all of them they will be granted the perk.
broken avatar :(
×
broken avatar :(
Location: us
Date Registered: 13 July 2016
Last active: 1054 days ago
Posts
17
Respect
Forum Rank
Legless Crawler
Primary Group
Member
×
kingneo's Groups
kingneo's Contact & Social Links
This should be pretty simple for you to implement. What you'll need to do is setup some trigger_damage brushes around the teddy bear models and monitor when players shoot them.

Here is code that will do that for you:

In the main function add:
callback::on_spawned( &on_player_spawned );
This will allow you to use on_player_spawned within your file.

And this, which checks your map for any triggers with the "teddy_trigger" targetname and sets up the logic for them:
level.teddy_triggers = getEntArray( "teddy_trigger", "targetname" );
    if( isDefined( level.teddy_triggers ) )
    {
        id = 0;
        foreach( trigger in level.teddy_triggers )
        {
            trigger thread teddy_think(id);
            id++;
        }
    }

Add the on_player_spawned function. This sets a variable to monitor how many teddies the player has shot, and ties the not shot/shot state to the player, meaning progress towards the perk is personal for each player.
function on_player_spawned()
{
    self notify( "teddy_check" );
   
    self.teddy_triggered_count = 0;
   
    // Used so multiple players can do the process, rather than tying progress to the teddies
    self.teddy_states = [];
    for( i = 0; i < level.teddy_triggers.size; i++ )
    {
        self.teddy_states[i] = false;
    }
}

Add the logic for the teddy triggers:
function teddy_think( id )
{
    while(1)
    {
        self waittill( "damage", amount, attacker, directionVec, point, type );
       
        if( !IsDefined( attacker ) || !IsPlayer( attacker ) )
{
WAIT_SERVER_FRAME;
continue;
}
       
        if( IsPlayer( attacker ) )
        {
            if( IsDefined( attacker.teddy_states ) && attacker.teddy_states[id] == false )
            {
                attacker.teddy_states[id] = true;
                attacker thread checkTeddyProgress();
            }
        }
    }
}
This monitors the trigger for any damage events, and once one happens, checks that it comes from player. If the player hasn't shot the teddy before, it will set that teddy to true for the player, and check the player's progress.

Add the checkTeddyProgress function:
function checkTeddyProgress()
{
    count = 0;
    foreach( entry in self.teddy_states )
    {
        if( entry == true )
        {
            count++;
        }
    }
   
    // They have hit every teddy
    if( count >= level.teddy_triggers.size )
    {
        self _zm_perks::give_perk( "marathon_perk" );
    }
}
This is called when the player hits any of the teddies, so once they've hit all of them they will be granted the perk.

Thanks so much man! This is really detailed and I understand it very well. Just two questions for ya though:
1) Do I put this code in it's own script file? As in it's own .gsc, .csc or .gsh file? Or do I just put it in the mapname.gsc script inside of the map's script folder?
2) Would there be any way to make it check for a specific type of damage, for example, splash damage from a Widow's Wine grenade? If not that's cool, I'm happy with how it works already!
broken avatar :(
×
broken avatar :(
Location: us
Date Registered: 13 July 2016
Last active: 1054 days ago
Posts
17
Respect
Forum Rank
Legless Crawler
Primary Group
Member
×
kingneo's Groups
kingneo's Contact & Social Links
EDIT:
When implementing this into the the mapname.gsc file, I get two errors: one that happens when I load the map, the map crashes and this error is given: "Error during initialization: attempting to PMem_Free 'PerLocalClient' but it is not at the top of the stack".

I also get an error when building/linking that says this: "^1ERR(6E) scripts/zm/zm_tutorial.gsc (155,1)  : Compiler Internal Error :  Unresolved external '_zm_perks::give_perk'"
broken avatar :(
×
broken avatar :(
Location: gb
Date Registered: 4 October 2016
Last active: 1037 days ago
Posts
10
Respect
Forum Rank
Legless Crawler
Primary Group
Member
×
Xylozi's Groups
Xylozi's Contact & Social Links
Not sure amount the first error, but for the one that occurs during linking, you need to add
#using scripts\zm\_zm_perks;
above the main function.

Here is a full script that you should be able to use more easily:
#using scripts\zm\_zm_perks;

function main()
{
zm_usermap::main();

level._zombie_custom_add_weapons = &custom_add_weapons;
level.zones = [];
level.zone_manager_init_func = &usermap_test_zone_init;
init_zones[0] = "start_zone";
level thread zm_zonemgr::manage_zones( init_zones );

    // Allows you to add your own code to execute when a player spawns, without having to directly edit the function in _globallogic_player
    callback::on_spawned( &on_player_spawned );

    // Searches the map for triggers and threads the logic function for them, assigning an id as well
    level.shootable_triggers = getEntArray( "shootable_trigger", "targetname" );
    if( isDefined( level.shootable_triggers ) )
    {
        id = 0;
        foreach( trigger in level.shootable_triggers )
        {
            trigger thread shootable_trigger_think(id);
            id++;
        }
    }
}

function usermap_test_zone_init()
{
    // Your code here, depends on if you have zones setup
    /*
    zm_zonemgr::add_adjacent_zone( "start_zone", "zone_2", "zone_1_to_2_trigger" );
    zm_zonemgr::add_adjacent_zone( "zone_2", "zone_4", "zone_2_to_4_trigger" );
    zm_zonemgr::add_adjacent_zone( "zone_2", "zone_6", "zone_2_to_6_trigger" );
    zm_zonemgr::add_adjacent_zone( "zone_2", "zone_3", "zone_2_to_3_trigger" );
    zm_zonemgr::add_adjacent_zone( "zone_3", "zone_6", "zone_3_to_6_trigger" );
    zm_zonemgr::add_adjacent_zone( "zone_2", "zone_5", "zone_2_to_5_trigger" );
    */
}

function custom_add_weapons()
{
zm_weapons::load_weapon_spec_from_table("gamedata/weapons/zm/zm_levelcommon_weapons.csv", 1);
}


function on_player_spawned()
{
    self notify( "shootable_trigger_destroy" );
   
    self.shootable_triggers_shot = 0;
   
    // Used so multiple players can do the process, rather than tying progress to the teddies
    self.shootable_triggers_personal = [];
    for( i = 0; i < level.shootable_triggers_personal.size; i++ )
    {
        self.shootable_triggers_personal[i] = false;
    }
}

function shootable_trigger_think( id )
{
    while(1)
    {
        self waittill( "damage", amount, attacker, directionVec, point, type );
       
        if( !IsDefined( attacker ) || !IsPlayer( attacker ) )
{
WAIT_SERVER_FRAME;
continue;
}
       
        if( IsPlayer( attacker ) )
        {
            if( IsDefined( attacker.shootable_triggers_personal ) && attacker.shootable_triggers_personal[id] == false )
            {
                attacker.shootable_triggers_personal[id] = true;
                attacker thread checkProgress();
            }
        }
    }
}

function checkProgress()
{
    count = 0;
    foreach( entry in self.shootable_triggers_personal )
    {
        if( entry == true )
        {
            count++;
        }
    }
   
    // They have hit every teddy
    if( count >= level.shootable_triggers.size )
    {
        // Adds the perk, but doesn't handle the HUD part
        self _zm_perks::give_perk( "marathon_perk" );
    }
}
broken avatar :(
×
broken avatar :(
Location: us
Date Registered: 13 July 2016
Last active: 1054 days ago
Posts
17
Respect
Forum Rank
Legless Crawler
Primary Group
Member
×
kingneo's Groups
kingneo's Contact & Social Links
Not sure amount the first error, but for the one that occurs during linking, you need to add
#using scripts\zm\_zm_perks;
above the main function.

Here is a full script that you should be able to use more easily:
#using scripts\zm\_zm_perks;

function main()
{
zm_usermap::main();

level._zombie_custom_add_weapons = &custom_add_weapons;
level.zones = [];
level.zone_manager_init_func = &usermap_test_zone_init;
init_zones[0] = "start_zone";
level thread zm_zonemgr::manage_zones( init_zones );

    // Allows you to add your own code to execute when a player spawns, without having to directly edit the function in _globallogic_player
    callback::on_spawned( &on_player_spawned );

    // Searches the map for triggers and threads the logic function for them, assigning an id as well
    level.shootable_triggers = getEntArray( "shootable_trigger", "targetname" );
    if( isDefined( level.shootable_triggers ) )
    {
        id = 0;
        foreach( trigger in level.shootable_triggers )
        {
            trigger thread shootable_trigger_think(id);
            id++;
        }
    }
}

function usermap_test_zone_init()
{
    // Your code here, depends on if you have zones setup
    /*
    zm_zonemgr::add_adjacent_zone( "start_zone", "zone_2", "zone_1_to_2_trigger" );
    zm_zonemgr::add_adjacent_zone( "zone_2", "zone_4", "zone_2_to_4_trigger" );
    zm_zonemgr::add_adjacent_zone( "zone_2", "zone_6", "zone_2_to_6_trigger" );
    zm_zonemgr::add_adjacent_zone( "zone_2", "zone_3", "zone_2_to_3_trigger" );
    zm_zonemgr::add_adjacent_zone( "zone_3", "zone_6", "zone_3_to_6_trigger" );
    zm_zonemgr::add_adjacent_zone( "zone_2", "zone_5", "zone_2_to_5_trigger" );
    */
}

function custom_add_weapons()
{
zm_weapons::load_weapon_spec_from_table("gamedata/weapons/zm/zm_levelcommon_weapons.csv", 1);
}


function on_player_spawned()
{
    self notify( "shootable_trigger_destroy" );
   
    self.shootable_triggers_shot = 0;
   
    // Used so multiple players can do the process, rather than tying progress to the teddies
    self.shootable_triggers_personal = [];
    for( i = 0; i < level.shootable_triggers_personal.size; i++ )
    {
        self.shootable_triggers_personal[i] = false;
    }
}

function shootable_trigger_think( id )
{
    while(1)
    {
        self waittill( "damage", amount, attacker, directionVec, point, type );
       
        if( !IsDefined( attacker ) || !IsPlayer( attacker ) )
{
WAIT_SERVER_FRAME;
continue;
}
       
        if( IsPlayer( attacker ) )
        {
            if( IsDefined( attacker.shootable_triggers_personal ) && attacker.shootable_triggers_personal[id] == false )
            {
                attacker.shootable_triggers_personal[id] = true;
                attacker thread checkProgress();
            }
        }
    }
}

function checkProgress()
{
    count = 0;
    foreach( entry in self.shootable_triggers_personal )
    {
        if( entry == true )
        {
            count++;
        }
    }
   
    // They have hit every teddy
    if( count >= level.shootable_triggers.size )
    {
        // Adds the perk, but doesn't handle the HUD part
        self _zm_perks::give_perk( "marathon_perk" );
    }
}

Okay cool, thanks again for the help!

However, when I ad the #using command for the _zm_perks script, it still gives me that same error when linking. It says that unresolved external thing for the command "_zm_perks::give_perk"

 

Login

or login with an authentication provider below
Sign In with Google
Sign In with Twitter
Sign In with Discord
Sign In with Steam
Sign In with Twitch
Loading ...