UGX-Mods

Call of Duty: Black Ops 3 => Help Desk => Scripting => Topic started by: Wolfilms on June 11, 2017, 10:58:49 pm

Title: Make the zombies ignore you?
Post by: Wolfilms on June 11, 2017, 10:58:49 pm
How do I make it so that when I step into a trigger, all the zombies go somewhere else and ignore me?
Title: Re: Make the zombies ignore you?
Post by: Archaicvirus on June 13, 2017, 09:01:06 pm
Create a script_struct in radiant, give it a targetname of custom_poi. Then create a trigger_multiple where you want the safe zone to be. Now, select the struct first, then select the trigger, hit W to link them. Place the struct where you want the zombies to go when you're in the exclusion zone. Then do this in gsc:
Code Snippet
Plaintext
#using scripts\codescripts\struct;
#using scripts\zm\_zm_utility;
#using scripts\shared\flag_shared; //edit: You might need this too

function poi_test(){
        level flag::wait_till("all_players_connected"); //edit
poi = struct::get("custom_poi", "targetname");
poi.trig = GetEnt(poi.target, "targetname");
poi.trig SetCursorHint("HINT_NOICON");
poi.trig SetHintString("Zombie exclusion volume");
// attract_dist, num_attractors, added_poi_value, start_turned_on, initial_attract_func, arrival_attract_func, poi_team
poi zm_utility::create_zombie_point_of_interest(100000, 99, 25, false);
// num_attract_dists, attract_dist
poi thread zm_utility::create_zombie_point_of_interest_attractor_positions(5, 100);
poi thread zm_utility::wait_for_attractor_positions_complete();
while(1){
poi.trig waittill("trigger", player);
if(player IsTouching(poi.trig)){
while(player IsTouching(poi.trig)){
poi.poi_active = true; //Turns point of interest on
wait(1);
}
}else
poi.poi_active = false; //Turns point of interest off
wait(1);
}
}
Title: Re: Make the zombies ignore you?
Post by: Wolfilms on June 13, 2017, 09:12:55 pm
I will test this when I get the chance, so thanks! But 1 question I have is how linking the struct and the trigger change the outcome of what the zombies do?
Title: Re: Make the zombies ignore you?
Post by: Archaicvirus on June 13, 2017, 09:20:30 pm
Linking the struct to the trigger does nothing, other then making the trigger easier to grab in script. It's just something I generally do to keep things simple. But essentially when you link two objects, the object that targets the other gains the kvp: target: (targetname of targeted object). So now struct.target equals the targetname of the object that the struct is targeting. COnfusing?
Title: Re: Make the zombies ignore you?
Post by: Wolfilms on June 13, 2017, 09:21:52 pm
It's a little confusing, but I think I understand. Thanks
Title: Re: Make the zombies ignore you?
Post by: Archaicvirus on June 13, 2017, 09:39:44 pm
Haha yea sorry man, it's kind of hard to explain, but it's really easy in the end.

Double Post Merge: June 13, 2017, 10:04:39 pm
Actually to be honest, linking the two objects does do more then what I described before. Generally when you link objects, the targeted object will auto-generate a targetname kvp. It will be like "auto1" or if you've linked a lot of objects, "auto17". This is useful for a lot of different reasons. Lets say you wanted to make multiple exclusion zones, you could link the two objects like I said, then save them as a prefab. So when you stamp copies of that prefab around the map, the targetname of the struct will stay the same, but each trigger will have an "auto3" or some number generated unique to it's parent's struct. That way you could do something like this:
Code Snippet
Plaintext
	function init(){
                //Edit - changed to struct::get_array not struct::get.
points = struct::get_array("exclusion_zone", "script_noteworthy");
foreach(point in points){
point.trig = GetEnt(point.target, "targetname");
point zm_utility::create_zombie_point_of_interest(100000, 99, 25, false);
point thread zm_utility::create_zombie_point_of_interest_attractor_positions(5, 100);
point thread zm_utility::wait_for_attractor_positions_complete();
point thread exclusion_zone();
}
}

function exclusion_zone(){
self.trig SetCursorHint("HINT_NOICON");
self.trig SetHintString("Exclusion Volume");
while(1){
self.trig waittill("trigger", player);
if(player IsTouching(self.trig)){
self.poi_active = true;
wait(1);
}else{
self.poi_active = false;
wait(1);
}
}
}

I haven't tested this exact script, but it comes from one of my scripts and I'm doing something similar, although I wrote this a little different for your application. But again linking objects does have a benefit depending on what you're trying to do. This method makes it so you don't have to write a separate function each time you want to make another exclusion zone. And also I haven't tried this with a trigger multiple, but I have this working on a trigger_use. So you might not want a hintstring on a trigger multiple.

Another idea you could do, is make multiple exclusion zones (triggers), but link only one struct to all of them, so no matter which exclusion zone the player is in, the zombies will always go to the same place.
Title: Re: Make the zombies ignore you?
Post by: Wolfilms on June 13, 2017, 10:52:20 pm
Oh wow, great explanation. Thank you. But another question I have, that I've seen in other code, what does foreach() do and how do you use it?
Title: Re: Make the zombies ignore you?
Post by: Archaicvirus on June 14, 2017, 12:27:29 am
Foreach means you are iterating through an array (in this case), so you are saying for each item in this group, do this to them. Here's a more practical explanation.

Code Snippet
Plaintext
function test()
{
        //Edit - adjusted for clarity

        //First, define the array.
        //Objects excluding script_struct's in radaint should use GetEntArray("key", "value"); and not struct::get_array
poi_array = struct::get_array("exclusion_zone", "targetname");
        //Let's say you have 5 structs all named exclusion_zone

        //When you do a foreach() loop, you can name the 'item' in the 'group' anything you want
        //For example below, 'foreach(struct in poi_array)' you can call 'struct' anything, it's a temporary variable only defined
        //within the for() loop.
        //Like foreach(thing in things), or foreach(guy in things), but the 'things' has to be an array, that you
        //define outside of and before the for() loop occurs. This can be used with any array, regardless of it's contents or application.
foreach(struct in poi_array)
{
//For each struct in the array "poi_array" defined above,
//execute this code 1 time for each struct:

                struct.trig = GetEnt(struct.target, "targetname");
struct thread some_function();
}

}

function test2()
{
poi_array = struct::get_array("exclusion_zone", "targetname");
//Let's say you have 5 structs all named exclusion_zone

//This is the same as foreach, except in an array,
//the first object is index 0, then 1, 2 etc.
//And you loop through that array with 'i' which starts at 0,
//and loops until poi_array[4], which would be the 5th index.
for(i = 0; i < poi_array.size; i++)
{

IPrintLnBold("Hello I am struct #:"+i);
trigger = GetEnt(poi_array[i].target, "targetname");
poi_array[i].trig = trigger;
poi_array[i] thread some_function();

}
}

function some_function()
{
//Each poi struct becomes 'self' in this function.
//So self.trig is the same as poi_array[i].trig above or struct.trig in the first function

self.trig waittill("trigger", player);
IPrintLnBold("Hello my target is at"+self.trig.origin);
}

//Or, if you're really hungry, you could do
function get_donuts(){
        a_dozen = GetEntArray("box_of_donuts", "script_food");
        foreach(donut in a_dozen){
        donut thread deep_fry();
        while(donut.is_cooking){
                donut waittill("minimum internal temperature reached");
                donut.is_done_cooking = true;
        }
        donut thread dip_in_chocolate_glaze();
        donut thread cover_in_sprinkles();
        break;        //For a taste test. :)

}

Hope that explains it a little better.

edit* - Fixed some typos in the scripts and the earlier replies as well.
Title: Re: Make the zombies ignore you?
Post by: Wolfilms on June 14, 2017, 01:28:30 pm
That is a great explanation. Thanks :)
Title: Re: Make the zombies ignore you?
Post by: Archaicvirus on June 14, 2017, 11:59:50 pm
Glad to help man, just let me know how it works out for you with an answer, if you would.
Title: Re: Make the zombies ignore you?
Post by: Wolfilms on June 16, 2017, 10:08:49 pm
Ok, so I just tested it. It works, but after I leave the trigger the zombies keep going to the script_struct. Any thoughts on why?
Title: Re: Make the zombies ignore you?
Post by: Archaicvirus on June 17, 2017, 05:04:57 am
I got your pm, but if you don't mind, post the exact script you're using in code tags here, and I'll take a look at it. That way other people can learn from this, and I can see which one of my examples you're using. And also, what is your radiant setup? Give me a brief explanation on the trigger and struct setup you have. A screen shot of their kvp's will also help.

 
Title: Re: Make the zombies ignore you?
Post by: Wolfilms on June 17, 2017, 01:36:10 pm
Code Snippet
Plaintext
#using scripts\codescripts\struct;

#using scripts\shared\array_shared;
#using scripts\shared\callbacks_shared;
#using scripts\shared\clientfield_shared;
#using scripts\shared\compass;
#using scripts\shared\exploder_shared;
#using scripts\shared\flag_shared;
#using scripts\shared\laststand_shared;
#using scripts\shared\math_shared;
#using scripts\shared\scene_shared;
#using scripts\shared\util_shared;

//custom

//custom

#insert scripts\shared\shared.gsh;
#insert scripts\shared\version.gsh;

#insert scripts\zm\_zm_utility.gsh;

#using scripts\zm\_load;
#using scripts\zm\_zm;
#using scripts\zm\_zm_audio;
#using scripts\zm\_zm_powerups;
#using scripts\zm\_zm_utility;
#using scripts\zm\_zm_weapons;
#using scripts\zm\_zm_zonemgr;

#using scripts\shared\ai\zombie_utility;

//Perks
#using scripts\zm\_zm_pack_a_punch;
#using scripts\zm\_zm_pack_a_punch_util;
#using scripts\zm\_zm_perk_additionalprimaryweapon;
#using scripts\zm\_zm_perk_doubletap2;
#using scripts\zm\_zm_perk_deadshot;
#using scripts\zm\_zm_perk_juggernaut;
#using scripts\zm\_zm_perk_quick_revive;
#using scripts\zm\_zm_perk_sleight_of_hand;
#using scripts\zm\_zm_perk_staminup;

//Powerups
#using scripts\zm\_zm_powerup_double_points;
#using scripts\zm\_zm_powerup_carpenter;
#using scripts\zm\_zm_powerup_fire_sale;
#using scripts\zm\_zm_powerup_free_perk;
#using scripts\zm\_zm_powerup_full_ammo;
#using scripts\zm\_zm_powerup_insta_kill;
#using scripts\zm\_zm_powerup_nuke;
//#using scripts\zm\_zm_powerup_weapon_minigun;

//Traps
#using scripts\zm\_zm_trap_electric;

#using scripts\zm\zm_usermap;

//*****************************************************************************
// MAIN
//*****************************************************************************

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

level._zombie_custom_add_weapons =&custom_add_weapons;

//Setup the levels Zombie Zone Volumes
level.zones = [];
level.zone_manager_init_func =&usermap_test_zone_init;
init_zones[0] = "start_zone";
level thread zm_zonemgr::manage_zones( init_zones );

level thread poi_test();

level.pathdist_type = PATHDIST_ORIGINAL;
}

function usermap_test_zone_init()
{
level flag::init( "always_on" );
level flag::set( "always_on" );
}

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

function poi_test(){
        level flag::wait_till("all_players_connected"); //edit
poi = struct::get("custom_poi", "targetname");
poi.trig = GetEnt(poi.target, "targetname");
poi.trig SetCursorHint("HINT_NOICON");
poi.trig SetHintString("Zombie exclusion volume");
// attract_dist, num_attractors, added_poi_value, start_turned_on, initial_attract_func, arrival_attract_func, poi_team
poi zm_utility::create_zombie_point_of_interest(100000, 99, 25, false);
// num_attract_dists, attract_dist
poi thread zm_utility::create_zombie_point_of_interest_attractor_positions(5, 100);
poi thread zm_utility::wait_for_attractor_positions_complete();
while(1){
poi.trig waittill("trigger", player);
if(player IsTouching(poi.trig)){
while(player IsTouching(poi.trig)){
poi.poi_active = true;//Turns point of interest on
IPrintLnBold("Inside");
wait(1);
}
}else
poi.poi_active = false;//Turns point of interest off
IPrintLnBold("Outside!");
wait(1);
}
}
Here are the images of radiant and the KVPs: http://imgur.com/a/Jps4t (http://imgur.com/a/Jps4t)
Title: Re: Make the zombies ignore you?
Post by: Archaicvirus on June 17, 2017, 06:14:14 pm
Thanks for the info,  give me a few and Ill respond on my pc.
Title: Re: Make the zombies ignore you?
Post by: BluntStuffy on June 17, 2017, 07:19:16 pm
Code Snippet
Plaintext
if(player IsTouching(poi.trig)){
while(player IsTouching(poi.trig)){
poi.poi_active = true;//Turns point of interest on
IPrintLnBold("Inside");
wait(1);
}
}else
poi.poi_active = false;//Turns point of interest off
IPrintLnBold("Outside!");
wait(1);

don tuse the else-statement here, the if-statement was allready true so it wont execute the code under the else-statement
Title: Re: Make the zombies ignore you?
Post by: Archaicvirus on June 17, 2017, 07:54:08 pm
Code Snippet
Plaintext
if(player IsTouching(poi.trig)){
while(player IsTouching(poi.trig)){
poi.poi_active = true;//Turns point of interest on
IPrintLnBold("Inside");
wait(1);
}
}else
poi.poi_active = false;//Turns point of interest off
IPrintLnBold("Outside!");
wait(1);

don tuse the else-statement here, the if-statement was allready true so it wont execute the code under the else-statement

Thanks for the correction man.

He's right, this is where the problem is.
Title: Re: Make the zombies ignore you?
Post by: Wolfilms on June 17, 2017, 09:41:08 pm
Ok, thanks guys! I’ll test it on Monday when I get home!
Title: Re: Make the zombies ignore you?
Post by: Wolfilms on June 20, 2017, 02:49:25 am
So all I did was take out the else statement, but nothing changed in the game. The zombies still always go to the POI even after I leave the trigger.
Title: Re: Make the zombies ignore you?
Post by: buttkicker845 on June 20, 2017, 04:06:01 am
remove the line
Code Snippet
Plaintext
poi.trig waittill("trigger", player);
if(player IsTouching(poi.trig)){
and replace it with
Code Snippet
Plaintext
if(isPlayer(player) &&  player IsTouching(poi.trig)){
if you keep the code the same as the original expect for this change it should work
Title: Re: Make the zombies ignore you?
Post by: Archaicvirus on June 20, 2017, 05:03:40 am
So all I did was take out the else statement, but nothing changed in the game. The zombies still always go to the POI even after I leave the trigger.

You could always do some type of cooldown. That's how I have mine set up and it's working fine. I'm using a trigger_use though, and it just waits 60 seconds then sets poi.poi_active to false then waits for trigger input again. That might be a better way to do it. Although it is possible to do it the way you're doing it, for some reason poi.poi_active isn't getting set to false. You could do something like this

Code Snippet
Plaintext
function poi_test(){
level flag::wait_till("all_players_connected"); //edit
poi = struct::get("custom_poi", "targetname");
poi.trig = GetEnt(poi.target, "targetname");
poi.trig SetCursorHint("HINT_NOICON");
poi.trig SetHintString("");
// attract_dist, num_attractors, added_poi_value, start_turned_on, initial_attract_func, arrival_attract_func, poi_team
poi zm_utility::create_zombie_point_of_interest(100000, 99, 25, false);
// num_attract_dists, attract_dist
poi thread zm_utility::create_zombie_point_of_interest_attractor_positions(5, 100);
poi thread zm_utility::wait_for_attractor_positions_complete();
coolDown = 5; //Change coolDown to whatever time you want
while(1){
poi.trig waittill("trigger", player);
poi.poi_active = true;
wait(coolDown);
poi.poi_active = false;
}
}
Title: Re: Make the zombies ignore you?
Post by: Harry Bo21 on June 20, 2017, 12:36:19 pm
doing this will break on co-op

everyone will be safe as long as one person is in the POI
Title: Re: Make the zombies ignore you?
Post by: Wolfilms on June 20, 2017, 02:11:33 pm
doing this will break on co-op

everyone will be safe as long as one person is in the POI

Is it possible to have it so that every player in the game has to hit a trigger?
Title: Re: Make the zombies ignore you?
Post by: Harry Bo21 on June 20, 2017, 02:13:43 pm
not using POI no
Title: Re: Make the zombies ignore you?
Post by: Wolfilms on June 20, 2017, 02:20:56 pm
Ok thanks
Title: Re: Make the zombies ignore you?
Post by: Archaicvirus on June 20, 2017, 07:06:00 pm
Is it possible to have it so that every player in the game has to hit a trigger?

Like I said before it's probably a lot easier just to make the trig a trigger_use, I have it working fine this way. This is the exact script I'm using with only minor changes to take out some of my checks.

Code Snippet
Plaintext
//Put these three in your main() function at the bottom
level flag::wait_till("all_players_connected");
poi = poi_setup();
poi thread poi_test();

//These are the two functions I'm using
function poi_setup(){
poi = struct::get("custom_poi", "targetname");
poi.trig = GetEnt(poi.target, "targetname");
poi.trig SetCursorHint("HINT_NOICON");
poi.hint = "Press &&1 to distract zombies"; //Or whatever hint you want
poi.trig SetHintString(poi.hint);
//poi.poi_active = false; *Edit - not needed, is set to false by default in create_zombie_point_of_interest(100000, 99, 25, false);<-here
// attract_dist, num_attractors, added_poi_value, start_turned_on, initial_attract_func, arrival_attract_func, poi_team
poi zm_utility::create_zombie_point_of_interest(100000, 99, 25, false);
// num_attract_dists, attract_dist
poi thread zm_utility::create_zombie_point_of_interest_attractor_positions(5, 100);
poi thread zm_utility::wait_for_attractor_positions_complete();
return poi;
}

function poi_test(){
while(1){
self.trig waittill("trigger");
self.poi_active = true;
cooldown = 15; //Change to time desired - I'm using 15 for testing
while(1){
if(cooldown > 0){
cooldown--;
self.trig SetHintString("Cooling down in ["+cooldown+"]..."); //This updates the trig with time left
wait(1);
}else
break;
}
self.poi_active = false;
self.trig SetHintString(self.hint);
}
}


Also this is just a proof of concept script that I made, so you should think about a way to limit this so players can't just keep using it over and over again. The cooldown in the script really should be called "poi active time" or something like that, because cooldown makes more sense to be the time after the poi expires, and before it can be triggered again. You can use a simple wait(time) or some other check. Here's a short vid demonstrating how I'm using it with the script I provided you.

Title: Re: Make the zombies ignore you?
Post by: Wolfilms on June 20, 2017, 07:11:27 pm
Like I said before it's probably a lot easier just to make the trig a trigger_use, I have it working fine this way. This is the exact script I'm using with only minor changes to take out some of my checks.

Code Snippet
Plaintext
//Put these three in your main() function at the bottom
level flag::wait_till("all_players_connected");
poi = poi_setup();
poi thread poi_test();

//These are the two functions I'm using
function poi_setup(){
poi = struct::get("custom_poi", "targetname");
poi.trig = GetEnt(poi.target, "targetname");
poi.trig SetCursorHint("HINT_NOICON");
poi.hint = "Press &&1 to distract zombies"; //Or whatever hint you want
poi.trig SetHintString(poi.hint);
poi.poi_active = false;
// attract_dist, num_attractors, added_poi_value, start_turned_on, initial_attract_func, arrival_attract_func, poi_team
poi zm_utility::create_zombie_point_of_interest(100000, 99, 25, false);
// num_attract_dists, attract_dist
poi thread zm_utility::create_zombie_point_of_interest_attractor_positions(5, 100);
poi thread zm_utility::wait_for_attractor_positions_complete();
return poi;
}

function poi_test(){
while(1){
self.trig waittill("trigger");
self.poi_active = true;
cooldown = 15; //Change to time desired - I'm using 15 for testing
while(1){
if(cooldown > 0){
cooldown--;
self.trig SetHintString("Cooling down in ["+cooldown+"]..."); //This updates the trig with time left
wait(1);
}else
break;
}
self.poi_active = false;
self.trig SetHintString(self.hint);
}
}


Also this is just a proof of concept script that I made, so you should think about a way to limit this so players can't just keep using it over and over again. The cooldown in the script really should be called "poi active time" or something like that, because cooldown makes more sense to be the time after the poi expires, and before it can be triggered again. You can use a simple wait(time) or some other check. Here's a short vid demonstrating how I'm using it with the script I provided you.

(Content removed from quote.)

Ok, thanks. I planned on making this just like a cool, hidden feature in my map so in no way do I intend to make it OP. Thanks everyone!
Title: Re: Make the zombies ignore you?
Post by: buttkicker845 on June 20, 2017, 07:12:20 pm
does the
Code Snippet
Plaintext
player.ignoreme 
variable still exist in bo3?
if it does you could just do something like this
Code Snippet
Plaintext
function poi_test(){
        level flag::wait_till("all_players_connected"); //edit
trig = GetEnt("trig_name", "targetname"); //change trig_name to whatever
trig SetCursorHint("HINT_NOICON");
trig SetHintString("Zombie exclusion volume");
while(1){
players = GetPlayers();
for(i = 0; i < players.size(); i++)
{
players[i].ignoreme = players[i] isTouching(poi.trig);
}
wait(.05);
}
}

this can also be done with a volume instead of a trigger

PS:this is a quick example you want to do other checks before setting the .ignoreme variable such as if the player is in laststand because if you dont its possible they would become a target if they are downed and not in the trigger zone
Title: Re: Make the zombies ignore you?
Post by: Archaicvirus on June 20, 2017, 07:20:52 pm
does the
Code Snippet
Plaintext
player.ignoreme 
variable still exist in bo3?
if it does you could just do something like this
Code Snippet
Plaintext
function poi_test(){
        level flag::wait_till("all_players_connected"); //edit
trig = GetEnt("trig_name", "targetname"); //change trig_name to whatever
trig SetCursorHint("HINT_NOICON");
trig SetHintString("Zombie exclusion volume");
while(1){
players = GetPlayers();
for(i = 0; i < players.size(); i++)
{
players[i].ignoreme = players[i] isTouching(poi.trig);
}
wait(.05);
}
}

this can also be done with a volume instead of a trigger

PS:this is a quick example you want to do other checks before setting the .ignoreme variable such as if the player is in laststand because if you dont its possible they would become a target if they are downed and not in the trigger zone

That's a really good idea.

 I appreciate everyone else's input too, that's why I always come here to ugx. That and I'm always having problems myself lol