cod4-sdk/raw/maps/mo_globals.gsc
2008-01-19 00:00:00 +00:00

922 lines
No EOL
25 KiB
Text

#include common_scripts\utility;
#include maps\_utility;
#include maps\_anim;
#include maps\mo_tools;
main(name)
{
if(!isdefined(name))
{
assertmsg("mo_globals called without initialization variable. mo_globals::main(<level name>);");
return;
}
level.level_name = name;
switch(name)
{
case "descent":
{
level.strings["hint_detpack"] = &"DESCENT_HINTSTR_DETPACK";
precacheString(level.strings["hint_detpack"]);
}break;
}
friendly_main();
ai_generic_main();
misc_main();
interactive_main();
}
/************************************************************************************************************************************/
/************************************************************************************************************************************/
/* GENERIC AI LOGIC */
/************************************************************************************************************************************/
/************************************************************************************************************************************/
ai_generic_main()
{
spawners = getspawnerarray();
array_thread(spawners, ::ai_special_parameters);
}
ai_special_parameters()
{
if(isdefined(self.target) && isdefined(self.script_forcecolor))
self thread ai_nodebeforecolor_think();
if(!isdefined(self.script_parameters))
return;
attr = strtok(self.script_parameters, ":;, ");
for(i=0; i<attr.size; i++)
{
if(tolower(attr[i]) == "ignoreme")
{
i++;
if(int(attr[i]) == 0)
{
self.stopIgnoreNotifyEnt = attr[i];
i++;
self.stopIgnoreNotifyMsg = attr[i];
self thread ai_ignoreme_think();
}
else
{
self.stopIgnoreTime = int(attr[i]);
self thread ai_ignoreme_think();
}
}
else if(tolower(attr[i]) == "setforcegoal")
{
i++;
if(int(attr[i]) == 0)
{
self.stopForceGoalNotifyEnt = attr[i];
i++;
self.stopForceGoalNotifyMsg = attr[i];
self thread ai_setforcegoal_think();
}
else
{
self.stopForceGoalTime = int(attr[i]);
self thread ai_setforcegoal_think();
}
}
else if(tolower(attr[i]) == "setforcecolor")
{
i++;
self.setForceColorValue = attr[i];
assert(maps\_colors::colorIsLegit(self.setForceColorValue), "spawner at origin " + self.origin + " has non-legit setforcedcolor, " + self.setForceColorValue + ".");
i++;
if(int(attr[i]) == 0)
{
self.setForceColorNotifyEnt = attr[i];
i++;
self.setForceColorNotifyMsg = attr[i];
self thread ai_setforcecolor_think();
}
else
{
self.setForceColorTime = int(attr[i]);
self thread ai_setforcecolor_think();
}
}
else if(tolower(attr[i]) == "magicbulletshield")
{
i++;
if(int(attr[i]) == 0)
{
self.stopBulletShieldNotifyEnt = attr[i];
i++;
self.stopBulletShieldNotifyMsg = attr[i];
self thread ai_magicbulletshield_think();
}
else
{
self.stopBulletShieldTime = int(attr[i]);
self thread ai_magicbulletshield_think();
}
}
else if(tolower(attr[i]) == "floodspawner")
{
i++;
self.FloodSpawnCount = int(attr[i]);
self thread ai_floodspawn_think();
}
else if(tolower(attr[i]) == "forcespawn")
{
self.forcespawn = 1;
}
else if(tolower(attr[i]) == "nobackup")
{
self.no_check_wave = true;
}
}
}
ai_nodebeforecolor_think()
{
node = getnode(self.target, "targetname");
if(!isdefined(node))
return;
self endon("death");
while(1)
{
self waittill("spawned", guy);
if(spawn_failed(guy))
continue;
break;
}
wait .05;
guy setgoalnode(node);
if(isdefined(node.radius))
guy.goalradius = node.radius;
}
ai_floodspawn_think()
{
self endon("death");
while(1)
{
self waittill("spawned", guy);
if(spawn_failed(guy))
continue;
self.FloodSpawnCount--;
break;
}
while(self.FloodSpawnCount > 0)
{
guy waittill("death");
self.count = 1;
// soldier was deleted, not killed if this fails
// so dont wait - go straight to spawning
if ( isDefined( guy ) )
{
if ( !script_wait() )
wait (randomFloatRange( 5, 9 ));
}
while(1)
{
if ( isDefined( self.forcespawn ) )
guy = self stalingradSpawn();
else
guy = self doSpawn();
if(!spawn_failed(guy))
{
self.FloodSpawnCount--;
break;
}
wait (1);
}
}
waittillframeend;
self delete();
}
ai_magicbulletshield_think()
{
self endon("death");
while(1)
{
self waittill("spawned", guy);
if(spawn_failed(guy))
continue;
if(isdefined(self.stopBulletShieldTime))
guy.stopBulletShieldTime = self.stopBulletShieldTime;
else if(isdefined(self.stopBulletShieldNotifyMsg))
{
guy.stopBulletShieldNotifyEnt = self.stopBulletShieldNotifyEnt;
guy.stopBulletShieldNotifyMsg = self.stopBulletShieldNotifyMsg;
}
else
assertMsg ("spawner with targetname "+ self.targetname + "has incorrect script_parameters set: correct syntax is magicbulletshield: <time> / or magicbulletshield: <ent> <notify>");
guy thread ai_magicbulletshield_think2();
}
}
ai_magicbulletshield_think2()
{
self endon("death");
self endon ("internal_stop_magic_bullet_shield");
self thread magic_bullet_shield();
if(isdefined(self.stopForceGoalTime))
{
wait(self.stopForceGoalTime);
}
else
if(isdefined(self.stopForceGoalNotifyMsg))
{
if(tolower(self.stopForceGoalNotifyEnt) == "self")
self waittill(self.stopForceGoalNotifyMsg);
else if(tolower(self.stopForceGoalNotifyEnt) == "level")
level waittill(self.stopForceGoalNotifyMsg);
else
assertMsg ("spawner with targetname "+ self.targetname + "has invalid script_parameters set: valid entity notify params for magicbulletshield are 'self' and 'level'");
}
else
{
return;
}
self stop_magic_bullet_shield();
}
ai_setforcecolor_think()
{
self endon("death");
while(1)
{
self waittill("spawned", guy);
if(spawn_failed(guy))
continue;
guy.setForceColorValue = self.setForceColorValue;
if(isdefined(self.setForceColorTime))
guy.setForceColorTime = self.setForceColorTime;
else if(isdefined(self.setForceColorNotifyMsg))
{
guy.setForceColorNotifyEnt = self.setForceColorNotifyEnt;
guy.setForceColorNotifyMsg = self.setForceColorNotifyMsg;
}
else
assertMsg ("spawner with targetname "+ self.targetname + "has incorrect script_parameters set: correct syntax is setforcecolor: <time> / or setforcecolor: <ent> <notify>");
guy thread ai_setforcecolor_think2();
}
}
ai_setforcecolor_think2()
{
self endon("death");
if(isdefined(self.setForceColorTime))
wait(self.setForceColorTime);
else if(isdefined(self.setForceColorNotifyMsg))
{
if(tolower(self.setForceColorNotifyEnt) == "self")
self waittill(self.setForceColorNotifyMsg);
else if(tolower(self.setForceColorNotifyEnt) == "level")
level waittill(self.setForceColorNotifyMsg);
else
assertMsg ("spawner with targetname "+ self.targetname + "has invalid script_parameters set: valid entity notify params for setforcecolor are 'self' and 'level'");
}
self set_force_color(self.setForceColorValue);
}
ai_setforcegoal_think()
{
self endon("death");
while(1)
{
self waittill("spawned", guy);
if(spawn_failed(guy))
continue;
if(isdefined(self.stopForceGoalTime))
guy.stopForceGoalTime = self.stopForceGoalTime;
else if(isdefined(self.stopForceGoalNotifyMsg))
{
guy.stopForceGoalNotifyEnt = self.stopForceGoalNotifyEnt;
guy.stopForceGoalNotifyMsg = self.stopForceGoalNotifyMsg;
}
else
assertMsg ("spawner with targetname "+ self.targetname + "has incorrect script_parameters set: correct syntax is setforcegoal: <time> / or setforcegoal: <ent> <notify>");
guy thread ai_setforcegoal_think2();
}
}
ai_setforcegoal_think2()
{
self endon("death");
self set_forcegoal();
if(isdefined(self.stopForceGoalTime))
wait(self.stopForceGoalTime);
else if(isdefined(self.stopForceGoalNotifyMsg))
{
if(tolower(self.stopForceGoalNotifyEnt) == "self")
self waittill(self.stopForceGoalNotifyMsg);
else if(tolower(self.stopForceGoalNotifyEnt) == "level")
level waittill(self.stopForceGoalNotifyMsg);
else
assertMsg ("spawner with targetname "+ self.targetname + "has invalid script_parameters set: valid entity notify params for setforcegoal are 'self' and 'level'");
}
self unset_forcegoal();
}
ai_ignoreme_think()
{
self endon("death");
while(1)
{
self waittill("spawned", guy);
if(spawn_failed(guy))
continue;
if(isdefined(self.stopIgnoreTime))
guy.stopIgnoreTime = self.stopIgnoreTime;
else if(isdefined(self.stopIgnoreNotifyMsg))
{
guy.stopIgnoreNotifyEnt = self.stopIgnoreNotifyEnt;
guy.stopIgnoreNotifyMsg = self.stopIgnoreNotifyMsg;
}
else
assertMsg ("spawner with targetname "+ self.targetname + "has incorrect script_parameters set: correct syntax is ignoreme: <time> / or ignoreme: <ent> <notify>");
guy thread ai_ignoreme_think2();
}
}
ai_ignoreme_think2()
{
self endon("death");
self.ignoreme = true;
if(isdefined(self.stopIgnoreTime))
wait(self.stopIgnoreTime);
else if(isdefined(self.stopIgnoreNotifyMsg))
{
if(tolower(self.stopIgnoreNotifyEnt) == "self")
self waittill(self.stopIgnoreNotifyMsg);
else if(tolower(self.stopIgnoreNotifyEnt) == "level")
level waittill(self.stopIgnoreNotifyMsg);
else
assertMsg ("spawner with targetname "+ self.targetname + "has invalid script_parameters set: valid entity notify params for ignoreme are 'self' and 'level'");
}
self.ignoreme = false;
}
/************************************************************************************************************************************/
/************************************************************************************************************************************/
/* FRIENDLY REINFORCEMENTS LOGIC */
/************************************************************************************************************************************/
/************************************************************************************************************************************/
friendly_main()
{
level.friendly_globals = spawnstruct();
level.friendly_globals.max_num = 4;
level.friendly_globals.wav_num = 2;
level.friendly_globals.cur_num = 0;
level.friendly_globals.force_this_color = [];
triggers = getentarray("friendly_spawner", "script_noteworthy");
array_thread(triggers, ::friendly_trigger_think);
thread friendly_logic();
}
friendly_logic()
{
while(1)
{
level waittill("friendly_globals_check_wave");
num = level.friendly_globals.max_num - level.friendly_globals.cur_num;
if( num < level.friendly_globals.wav_num && !( (isdefined(level.fastrope_globals.heli_inflight)) && level.fastrope_globals.heli_inflight == true ) )
continue;
for(i=0; i<num; i++)
{
spawner = level.friendly_globals.curr_trigger friendly_cycle_spawner();
spawner thread friendly_spawner_think();
}
}
}
friendly_cycle_spawner()
{
start_index = self.spawner_index;
while(1)
{
self.spawner_index++;
if(self.spawner_array.size == self.spawner_index)
self.spawner_index = 0;
if(!level.friendly_globals.force_this_color.size)
break;
if(self.spawner_array[self.spawner_index] check_force_color(level.friendly_globals.force_this_color[level.friendly_globals.force_this_color.size-1]) )
{
level.friendly_globals.force_this_color = array_remove(level.friendly_globals.force_this_color, level.friendly_globals.force_this_color[level.friendly_globals.force_this_color.size-1]);
break;
}
if(start_index == self.spawner_index)
{
self.spawner_index++;
if(self.spawner_array.size == self.spawner_index)
self.spawner_index = 0;
break;
}
}
return self.spawner_array[self.spawner_index];
}
friendly_spawner_think()
{
self endon("death");
self.count = 1;
guy = self dospawn();
if (spawn_failed(guy))
return;
level.friendly_globals.cur_num++;
if(isdefined(self.script_noteworthy))
{
if(self.script_noteworthy == "repel_friendlies")
{
node = getstruct(self.targetname, "target");
guy thread friendly_repel_spawner_think(node);
}
}
self thread friendly_spawner_death(guy);
return guy;
}
friendly_spawner_death(guy)
{
self endon("death");
guy waittill_any("death", "get_off_friendly_logic");
if(isdefined(self.force_this_color))
level.friendly_globals.force_this_color[level.friendly_globals.force_this_color.size] = self.force_this_color;
level.friendly_globals.cur_num--;
if(isdefined(self.no_check_wave))
return;
level notify("friendly_globals_check_wave");
}
#using_animtree("generic_human");
friendly_repel_animload()
{
if(isdefined(level.global_repel_anims_loaded))
return;
level.scr_anim["repel_friendly"]["rappel"] = %rappel;
level.scr_anim["repel_friendly"]["aim"][0] = %stand_aim_straight;
level.global_repel_anims_loaded = true;
}
friendly_repel_spawner_think(node)
{
self endon("death");
self.animname = "repel_friendly";
self thread anim_loop_solo(self, "aim", undefined, "stop_aim");
wait randomfloat(1);
self notify("stop_aim");
node thread anim_single_solo (self, "rappel");
}
friendly_force_spawner_think(trigger)
{
while(1)
{
trigger waittill("trigger");
self thread friendly_spawner_think();
}
}
friendly_trigger_think()
{
//grab the friendlies who target this trigger
self.spawner_array = getentarray(self.targetname, "target");
self.spawner_index = 0;
//find out if any of the friendlies have special attributes
for(i=0; i < self.spawner_array.size; i++)
{
if(isdefined(self.spawner_array[i].script_parameters))
{
attr = strtok( self.spawner_array[i].script_parameters, ":;, " );
for(j=0; j<attr.size; j++)
{
if(tolower(attr[j]) == "force_friendlies")
self.spawner_array[i] thread friendly_force_spawner_think(self);
if(tolower(attr[j]) == "force_this_color")
{
j++;
self.spawner_array[i].force_this_color = attr[j];
}
}
}
if(isdefined(self.spawner_array[i].script_noteworthy) && self.spawner_array[i].script_noteworthy == "repel_friendlies")
friendly_repel_animload();
}
//grab the spawn wave attributes for this trigger
self.max_num = self.spawner_array.size;
self.wav_num = 0;
if(isdefined(self.script_parameters))
{
attr = strtok( self.script_parameters, ", " );
switch(attr.size)
{
case 2:
self.max_num = int(attr[1]);
case 1:
self.wav_num = int(attr[0]);
}
}
//when it's triggered, set the global friendly params
while(1)
{
self waittill("trigger");
//dont process unless it's a different trigger
if(isdefined(level.friendly_globals.curr_trigger))
level.friendly_globals.curr_trigger trigger_on();
level.friendly_globals.curr_trigger = self;
if(self.max_num > 0)
level.friendly_globals.max_num = self.max_num;
if(self.wav_num > 0)
level.friendly_globals.wav_num = self.wav_num;
level notify("friendly_globals_check_wave");
self trigger_off();
}
}
/************************************************************************************************************************************/
/************************************************************************************************************************************/
/* TEMP BREAKABLES LOGIC */
/************************************************************************************************************************************/
/************************************************************************************************************************************/
interactive_main()
{
crates = getentarray("crate_breakable", "targetname");
crates thread interactive_precacheFX();
array_thread(crates, ::interactive_cratethink);
cardboardbox = getentarray("interactive_cardboard_box", "targetname");
cardboardbox thread interactive_precacheFX();
array_thread(cardboardbox, ::interactive_cardboardboxthink);
walls = getentarray("wall_breakable","targetname");
walls thread interactive_precacheFX();
array_thread(walls, ::interactive_wallthink);
fence = getentarray("fence_shootable", "targetname");
fence thread interactive_precacheFX();
array_thread(fence, ::interactive_fencethink);
}
interactive_precacheFX()
{
if(!self.size)
return;
if(self[0].targetname == "crate_breakable")
{
level._effect["exp_crate1"] = loadfx("props/crateExp_dust");
level._effect["exp_crate2"] = loadfx("props/crateExp_ammo");
return;
}
if(self[0].targetname == "wall_breakable")
{
level._effect["exp_wall"] = loadfx("props/wallExp_concrete");
return;
}
if(self[0].targetname == "fence_shootable")
{
level._effect["fence"] = loadfx("impacts/small_metalhit_1");
return;
}
}
interactive_fencethink()
{
self setcandamage(true);
while(1)
{
self waittill("damage", damage, other, direction_vec, P );
name = undefined;
start = P + vector_multiply(direction_vec, 1);
end = P + vector_multiply(direction_vec, 1024);
magicbullet("mp5", start, end);
playfx( level._effect["fence"], P, vector_multiply(direction_vec, -1));
}
}
interactive_wallthink()
{
self setcandamage(true);
vec = undefined;
node = undefined;
//if we have an axis node - then calculate the direction of the fx based on that
if(isdefined(self.target))
{
node = getent(self.target, "targetname");
if(isdefined(node.script_noteworthy) && node.script_noteworthy == "doorframe")
{
P = self getorigin();
N = undefined;
if(distance(P, node.origin) < node.radius)
N = node.origin;
else
{
//reposition our virtual node on the otherside of the frame
vec = anglesToForward (node.angles);
vec1 = vector_multiply(vec, 88);
N = node.origin + vec1;
}
vec = anglestoup(node.angles);
vec1 = vector_multiply(vec, 64);
A = N + vec1;
vec1 = vector_multiply(vec, -64);
B = N + vec1;
//calculate the vector derived from the center line of our wall and the point of break
vec = vectorFromLineToPoint(A, B, P);
}
if(isdefined(node.script_noteworthy) && node.script_noteworthy == "windowframe")
{
P = self getorigin();
N = undefined;
if(distance(P, node.origin) < node.radius)
N = node.origin;
else
{
//reposition our virtual node on the otherside of the frame
vec = anglesToForward (node.angles);
vec1 = vector_multiply(vec, 72);
N = node.origin + vec1;
}
vec = anglestoup(node.angles);
vec1 = vector_multiply(vec, 64);
A = N + vec1;
vec1 = vector_multiply(vec, -64);
B = N + vec1;
//calculate the vector derived from the center line of our wall and the point of break
vec = vectorFromLineToPoint(A, B, P);
}
else
{
A = node.origin;
vec = anglesToForward (node.angles);
vec = vector_multiply(vec, 128);
B = A+vec;
P = self getorigin();
//calculate the vector derived from the center line of our wall and the point of break
vec = vectorFromLineToPoint(A, B, P);
}
}
wait .1;
if(isdefined(node))
node delete();
self waittill("damage", damage, other, direction_vec, P );
self delete();
if(isdefined(vec))
playfx ( level._effect["exp_wall"], P, vec);
else
playfx ( level._effect["exp_wall"], P);
thread play_sound_in_space("stone_wall_impact_med", P);
}
interactive_cardboardboxthink()
{
self setcandamage(true);
up = (0,0,1);
time = 5;
while(1)
{
self waittill("damage", damage, other, direction_vec, P, type );
if(type == "MOD_MELEE" || type == "MOD_IMPACT")
continue;
ang = anglestoright(vectortoangles(direction_vec));
up = vector_multiply(up, randomfloatrange(400,600));
//vec = vector_multiply(ang, (randomfloat(1) - .5));
vec = direction_vec;
vec = vector_multiply(vec, 1.5);//(damage * randomfloatrange(2, 4)) );
vec += up;
impact = vector_multiply( (P - self.origin), .25);
self physicsLaunch( (self.origin + impact) , vec);
break;
}
//self delete();
}
interactive_cratethink()
{
self setcandamage(true);
if(isdefined(self.target))
{
self.debri = getent(self.target, "targetname");
self.debri hide();
}
self waittill("damage", damage, ent);//, direction_vec, P );
if(isdefined(self.debri))
self.debri show();
x = randomint(5);
if(x>0)
playfx(level._effect["exp_crate1"], self.origin);
else
playfx(level._effect["exp_crate2"], self.origin);
thread play_sound_in_space("wood_crate_break_med", self.origin);
others = getentarray("crate_breakable","targetname");
for (i=0;i<others.size;i++)
{
other = others[i];
//see if it's within 40 units from this box on X or Y
diffX = abs(self.origin[0] - other.origin[0]);
diffY = abs(self.origin[1] - other.origin[1]);
if ( (diffX <= 20) && (diffY <= 20) )
{
//see if it's above the box (would probably be resting on it)
diffZ = (self.origin[2] - other.origin[2]);
if (diffZ <= 0)
other notify ("damage", damage, ent);
}
}
self delete();
}
/************************************************************************************************************************************/
/************************************************************************************************************************************/
/* MISC LEVEL LOGIC */
/************************************************************************************************************************************/
/************************************************************************************************************************************/
misc_main()
{
saves = getentarray("autosave", "targetname");
array_thread(saves, ::auto_save_think);
bombs = getentarray("wall_breach_check", "targetname");
if(bombs.size)
{
precacheShader("hudStopwatch");
precacheShader("hudStopwatchNeedle");
precacheShader("objective");
}
array_thread(bombs, ::wall_breach_think);
level.scr_anim["player_link"]["loop"][0] = %bh_fastrope_loop;
level.scr_anim["player_link"]["land"] = %bh_fastrope_land;
}
auto_save_think()
{
self waittill("trigger");
if(isdefined(self.script_noteworthy))
autosave_by_name(self.script_noteworthy);
else
autosave_by_name("default");
}
wall_breach_think()
{
struct = spawnstruct();
struct.on = self;
struct.off = getent(struct.on.target, "targetname");
struct.obj_glow = getentarray(struct.off.target, "targetname");
struct.obj_mdl = getentarray(struct.obj_glow[0].target, "targetname");
struct.use_trig = getentarray(struct.obj_mdl[0].target, "targetname");
struct.whole = getent(struct.use_trig[0].target, "targetname");
struct.broken = getent(struct.whole.target, "targetname");
if(isdefined(struct.broken.target))
struct.chain = getent(struct.broken.target, "targetname");
struct.obj_glow[0] hide(); struct.obj_glow[1] hide();
struct.obj_mdl[0] hide(); struct.obj_mdl[1] hide();
struct.broken hide();
struct.whole disconnectpaths();
struct.use_trig[0].time = 4;
struct.use_trig[0] setHintString(level.strings["hint_detpack"]); struct.use_trig[1] setHintString(level.strings["hint_detpack"]);
struct endon("used");
struct thread wall_breach_think2();
while(1)
{
struct.on waittill("trigger");
struct notify("on");
struct.obj_glow[0] show(); struct.obj_glow[1] show();
struct.off waittill("trigger");
struct notify("off");
struct.obj_glow[0] hide(); struct.obj_glow[1] hide();
}
}
wall_breach_think2()
{
//self endon("off");
array_wait(self.use_trig, "trigger", 0);
//self.use_trig waittill("trigger", ent);
//if(!isdefined(ent) || ent != level.player)
//self.use_trig[0].time = 2;
self notify("used");
self.use_trig[0] trigger_off(); self.use_trig[1] trigger_off();
self.obj_glow[0] delete(); self.obj_glow[1] delete();
self.obj_mdl[0] show(); self.obj_mdl[1] show();
if(isdefined(self.use_trig[0].jumptoRandomType) || isdefined(self.use_trig[1].jumptoRandomType))
{
self.whole delete();
self.broken show();
if (self.broken.spawnflags & 1)
self.broken disconnectpaths();
return;
}
//show stopwatch
self.obj_mdl[0] playLoopSound("bomb_tick");
timer = get_stop_watch(60,self.use_trig[0].time);
wait ( self.use_trig[0].time * .5 );
thread play_sound_in_space(level.level_name + "_ge1_fireinhole", (self.on getorigin()));
wait ( self.use_trig[0].time * .5 );
self.obj_mdl[0] stopLoopSound( "bomb_tick" );
timer destroy();
playfx(level._effect["exp_breach"], self.obj_mdl[0].origin);
thread play_sound_in_space("detpack_explo_concrete", self.obj_mdl[0].origin);
/*
detpack_explo_metal
detpack_explo_wood
*/
self.use_trig[0] delete(); self.use_trig[1] delete();
self.whole delete();
self.obj_mdl[0] delete(); self.obj_mdl[1] delete();
self.broken show();
if (self.broken.spawnflags & 1)
self.broken disconnectpaths();
self.on delete();
self.off delete();
if(!isdefined(self.chain))
return;
wait(.5);
self.chain notify("trigger");
}