first commit
This commit is contained in:
912
mod_slipgate/source/server/ai.qc
Normal file
912
mod_slipgate/source/server/ai.qc
Normal file
@@ -0,0 +1,912 @@
|
||||
/*QUAKED path_corner (0.5 0.3 0) (-8 -8 -8) (8 8 8) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
If a monster targets a path_corner, they will move towards it.
|
||||
Once a monster hits a path_corner, they will move to the next targeted path_corner.
|
||||
You can set "pausetime" on a path_corner to enforce a delay before the monster moves
|
||||
to the next target.
|
||||
*/
|
||||
void() path_corner =
|
||||
{
|
||||
if (!self.targetname)
|
||||
{
|
||||
objerror ("path_corner: no targetname");
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
|
||||
self.movetype = MOVETYPE_NONE;
|
||||
self.solid = SOLID_TRIGGER;
|
||||
setsize (self, '-8 -8 -8', '8 8 8');
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
/*
|
||||
=============
|
||||
range
|
||||
|
||||
returns the range catagorization of an entity reletive to self
|
||||
0 melee range, will become hostile even if back is turned
|
||||
1 visibility and infront, or visibility and show hostile
|
||||
2 infront and show hostile
|
||||
3 only triggered by damage
|
||||
=============
|
||||
*/
|
||||
float(entity targ) range =
|
||||
{
|
||||
float r = vlen (self.origin + self.view_ofs - targ.origin + targ.view_ofs);
|
||||
if (r < 500)
|
||||
{
|
||||
if (r < 120)
|
||||
return RANGE_MELEE;
|
||||
else
|
||||
return RANGE_NEAR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (r < 1000)
|
||||
return RANGE_MID;
|
||||
else
|
||||
return RANGE_FAR;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
=============
|
||||
visible
|
||||
|
||||
returns 1 if the entity is visible to self, even if not infront ()
|
||||
=============
|
||||
*/
|
||||
float (entity targ) visible =
|
||||
{
|
||||
traceline (self.origin + self.view_ofs, targ.origin + targ.view_ofs, TRUE, self);
|
||||
if (trace_inwater)
|
||||
{
|
||||
if (trace_inopen)
|
||||
return FALSE;
|
||||
}
|
||||
if (trace_fraction == 1)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
infront
|
||||
|
||||
returns 1 if the entity is in front (in sight) of self
|
||||
=============
|
||||
*/
|
||||
float(entity targ) infront =
|
||||
{
|
||||
makevectors (self.angles);
|
||||
vector vec = normalize (targ.origin - self.origin);
|
||||
float dot = vec * v_forward;
|
||||
if (dot > 0.3)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
void() HuntTarget =
|
||||
{
|
||||
self.goalentity = self.enemy;
|
||||
self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
|
||||
self.think = self.th_run;
|
||||
self.nextthink = time + 0.1;
|
||||
SUB_AttackFinished(1); // wait a while before first attack
|
||||
};
|
||||
|
||||
void() SightSound =
|
||||
{
|
||||
if (self.classname == "monster_ogre")
|
||||
sound (self, CHAN_BODY, "ogre/ogwake.wav", 1, ATTN_NORM);
|
||||
else if (self.classname == "monster_knight")
|
||||
sound (self, CHAN_BODY, "knight/ksight.wav", 1, ATTN_NORM);
|
||||
else if (self.classname == "monster_shambler")
|
||||
sound (self, CHAN_BODY, "shambler/ssight.wav", 1, ATTN_NORM);
|
||||
else if (self.classname == "monster_demon1")
|
||||
sound (self, CHAN_BODY, "demon/sight2.wav", 1, ATTN_NORM);
|
||||
else if (self.classname == "monster_wizard")
|
||||
sound (self, CHAN_BODY, "wizard/wsight.wav", 1, ATTN_NORM);
|
||||
else if (self.classname == "monster_zombie")
|
||||
sound (self, CHAN_BODY, "zombie/z_idle.wav", 1, ATTN_NORM);
|
||||
else if (self.classname == "monster_dog")
|
||||
sound (self, CHAN_BODY, "dog/dsight.wav", 1, ATTN_NORM);
|
||||
else if (self.classname == "monster_hell_knight")
|
||||
sound (self, CHAN_BODY, "hknight/sight1.wav", 1, ATTN_NORM);
|
||||
else if (self.classname == "monster_tarbaby")
|
||||
sound (self, CHAN_BODY, "blob/sight1.wav", 1, ATTN_NORM);
|
||||
else if (self.classname == "monster_enforcer")
|
||||
{
|
||||
float r = randomrange(4);
|
||||
if (r == 0)
|
||||
sound (self, CHAN_BODY, "enforcer/sight1.wav", 1, ATTN_NORM);
|
||||
else if (r == 1)
|
||||
sound (self, CHAN_BODY, "enforcer/sight2.wav", 1, ATTN_NORM);
|
||||
else if (r == 2)
|
||||
sound (self, CHAN_BODY, "enforcer/sight3.wav", 1, ATTN_NORM);
|
||||
else
|
||||
sound (self, CHAN_BODY, "enforcer/sight4.wav", 1, ATTN_NORM);
|
||||
}
|
||||
else if (self.classname == "monster_army")
|
||||
sound (self, CHAN_BODY, "soldier/sight1.wav", 1, ATTN_NORM);
|
||||
else if (self.classname == "monster_shalrath")
|
||||
sound (self, CHAN_BODY, "shalrath/sight.wav", 1, ATTN_NORM);
|
||||
};
|
||||
|
||||
void() FoundTarget =
|
||||
{
|
||||
if (self.enemy.classname == "player")
|
||||
{
|
||||
sight_entity = self;
|
||||
sight_entity_time = time;
|
||||
}
|
||||
|
||||
self.show_hostile = time + 1; // wake up other monsters
|
||||
|
||||
SightSound ();
|
||||
HuntTarget ();
|
||||
};
|
||||
|
||||
/*==========
|
||||
FindTarget
|
||||
==========*/
|
||||
float() FindTarget =
|
||||
{
|
||||
if (intermission_running)
|
||||
return FALSE;
|
||||
|
||||
if (sight_entity_time >= time - 0.1 && !(self.spawnflags & MONSTER_AMBUSH) )
|
||||
{
|
||||
entity client = sight_entity;
|
||||
if (client.enemy == self.enemy)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
client = checkclient ();
|
||||
if (!client)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (client == self.enemy)
|
||||
return FALSE;
|
||||
|
||||
if (client.flags & FL_NOTARGET)
|
||||
return FALSE;
|
||||
if (client.items & IT_INVISIBILITY)
|
||||
return FALSE;
|
||||
|
||||
float r = range(client);
|
||||
if (r == RANGE_FAR)
|
||||
return FALSE;
|
||||
|
||||
if (!visible (client))
|
||||
return FALSE;
|
||||
|
||||
if (r == RANGE_NEAR)
|
||||
{
|
||||
if (client.show_hostile < time && !infront (client))
|
||||
return FALSE;
|
||||
}
|
||||
else if (r == RANGE_MID)
|
||||
{
|
||||
if (!infront (client))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// got one
|
||||
//
|
||||
self.enemy = client;
|
||||
if (self.enemy.classname != "player")
|
||||
{
|
||||
self.enemy = self.enemy.enemy;
|
||||
if (self.enemy.classname != "player")
|
||||
{
|
||||
self.enemy = world;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
FoundTarget ();
|
||||
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*==========
|
||||
ai_movetogoal
|
||||
==========*/
|
||||
|
||||
float (float dist) SV_CloseEnough =
|
||||
{
|
||||
if (self.goalentity.absmin.x > self.absmax.x + dist)
|
||||
return FALSE;
|
||||
if (self.goalentity.absmax.x < self.absmin.x - dist)
|
||||
return FALSE;
|
||||
|
||||
if (self.goalentity.absmin.y > self.absmax.y + dist)
|
||||
return FALSE;
|
||||
if (self.goalentity.absmax.y < self.absmin.y - dist)
|
||||
return FALSE;
|
||||
|
||||
if (self.goalentity.absmin.z > self.absmax.z + dist)
|
||||
return FALSE;
|
||||
if (self.goalentity.absmax.z < self.absmin.z - dist)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
|
||||
//.float blocked_time;
|
||||
//.float blocked_count;
|
||||
|
||||
void(entity goal, float dist) ai_movetogoal =
|
||||
{
|
||||
// new target
|
||||
if (self.goalentity != goal)
|
||||
{
|
||||
self.goalentity = goal;
|
||||
self.ideal_yaw = vectoyaw(goal.origin - self.origin);
|
||||
}
|
||||
|
||||
vector oldorigin = self.origin;
|
||||
movetogoal(dist);
|
||||
if (self.origin != oldorigin)
|
||||
return;
|
||||
|
||||
if (SV_CloseEnough(dist))
|
||||
{
|
||||
//dprint("SV_CloseEnough\n");
|
||||
self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
|
||||
changeyaw();
|
||||
if (walkmove(self.angles_y, dist))
|
||||
return;
|
||||
float ofs;
|
||||
if (self.lefty)
|
||||
ofs = 45;
|
||||
else
|
||||
ofs = -45;
|
||||
|
||||
if (walkmove(self.angles_y + ofs, dist))
|
||||
return;
|
||||
self.lefty = 1 - self.lefty;
|
||||
walkmove(self.angles_y - ofs, dist);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
if (self.blocked_count > 10)
|
||||
{
|
||||
self.blocked_count = 0;
|
||||
self.blocked_time = time + 5;
|
||||
}
|
||||
if (self.blocked_time > time)
|
||||
{
|
||||
movetogoal(dist);
|
||||
return;
|
||||
}
|
||||
|
||||
self.ideal_yaw = vectoyaw(goal.origin - self.origin);
|
||||
changeyaw();
|
||||
if (walkmove(self.angles_y, dist))
|
||||
return;
|
||||
|
||||
self.blocked_count = self.blocked_count + 1;
|
||||
float ofs;
|
||||
if (self.lefty)
|
||||
ofs = 45;
|
||||
else
|
||||
ofs = -45;
|
||||
|
||||
if (walkmove(self.angles_y + ofs, dist))
|
||||
return;
|
||||
|
||||
self.lefty = 1 - self.lefty;
|
||||
walkmove(self.angles_y - ofs, dist);*/
|
||||
};
|
||||
|
||||
|
||||
void(float dist) ai_forward =
|
||||
{
|
||||
walkmove(self.angles_y, dist);
|
||||
};
|
||||
|
||||
void(float dist) ai_back =
|
||||
{
|
||||
walkmove(self.angles_y + 180, dist);
|
||||
};
|
||||
|
||||
void(float dist) ai_pain =
|
||||
{
|
||||
ai_back(dist);
|
||||
};
|
||||
|
||||
void(float dist) ai_painforward =
|
||||
{
|
||||
ai_forward(dist);
|
||||
};
|
||||
|
||||
void(float dist) ai_walk =
|
||||
{
|
||||
if (FindTarget())
|
||||
return;
|
||||
|
||||
ai_movetogoal(self.movetarget, dist);
|
||||
if (vlen(self.origin - self.movetarget.origin) < 32)
|
||||
{
|
||||
entity targ = find(world, targetname, self.movetarget.target);
|
||||
if (targ.classname == "path_corner")
|
||||
{
|
||||
self.movetarget = self.goalentity = targ;
|
||||
self.ideal_yaw = vectoyaw(targ.origin - self.origin);
|
||||
if (targ.pausetime > 0)
|
||||
{
|
||||
self.think = self.th_stand;
|
||||
self.pausetime = time + targ.pausetime;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.think = self.th_stand;
|
||||
self.pausetime = -1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void() ai_stand =
|
||||
{
|
||||
if (FindTarget())
|
||||
return;
|
||||
|
||||
if (time > self.pausetime && self.pausetime > 0)
|
||||
{
|
||||
if (self.movetarget)
|
||||
{
|
||||
self.th_walk();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// random angle turns
|
||||
if (time > self.search_time)
|
||||
{
|
||||
self.search_time = time + 1 + random() * 2;
|
||||
|
||||
if (self.angles_y != self.ideal_yaw)
|
||||
self.angles_y = self.ideal_yaw;
|
||||
else
|
||||
{
|
||||
if (random() < 0.5)
|
||||
self.angles_y = self.ideal_yaw + random() * 30;
|
||||
else
|
||||
self.angles_y = self.ideal_yaw - random() * 30;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void() ai_turn =
|
||||
{
|
||||
if (FindTarget())
|
||||
return;
|
||||
changeyaw ();
|
||||
};
|
||||
|
||||
float(float ang) FacingIdeal =
|
||||
{
|
||||
float delta = angcomp(self.ideal_yaw, self.angles_y);
|
||||
if (delta > ang)
|
||||
return FALSE;
|
||||
if (delta < -ang)
|
||||
return FALSE;
|
||||
|
||||
/*float delta = anglemod(self.angles_y - self.ideal_yaw);
|
||||
if (delta > 45 && delta < 315)
|
||||
return FALSE;
|
||||
*/
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
float() WizardCheckAttack;
|
||||
float() DogCheckAttack;
|
||||
|
||||
float() CheckAnyAttack =
|
||||
{
|
||||
if (self.classname == "monster_ogre")
|
||||
return OgreCheckAttack ();
|
||||
if (!enemy_vis)
|
||||
return FALSE;
|
||||
if (self.classname == "monster_army")
|
||||
return SoldierCheckAttack ();
|
||||
if (self.classname == "monster_shambler")
|
||||
return ShamCheckAttack ();
|
||||
if (self.classname == "monster_demon1")
|
||||
return DemonCheckAttack ();
|
||||
if (self.classname == "monster_dog")
|
||||
return DogCheckAttack ();
|
||||
if (self.classname == "monster_wizard")
|
||||
return WizardCheckAttack ();
|
||||
return CheckAttack ();
|
||||
};
|
||||
|
||||
|
||||
/*==========
|
||||
ai_run_melee
|
||||
|
||||
Turn until facing enemy then launch melee attack
|
||||
==========
|
||||
*/
|
||||
void() ai_run_melee =
|
||||
{
|
||||
self.ideal_yaw = enemy_yaw;
|
||||
changeyaw();
|
||||
if (FacingIdeal(90))
|
||||
{
|
||||
self.th_melee ();
|
||||
self.attack_state = AS_STRAIGHT;
|
||||
}
|
||||
};
|
||||
|
||||
/*==============
|
||||
ai_run_missile
|
||||
|
||||
Turn until facing enemy then launch missile attack
|
||||
==========*/
|
||||
void() ai_run_missile =
|
||||
{
|
||||
if (self.attack_state == AS_SPAM)
|
||||
{
|
||||
self.ideal_yaw = vectoyaw(self.enemy_last - self.origin);
|
||||
changeyaw();
|
||||
}
|
||||
else
|
||||
{
|
||||
self.ideal_yaw = enemy_yaw;
|
||||
changeyaw();
|
||||
// if the enemy has dropped out of sight, cancel the attack
|
||||
if (!enemy_vis)
|
||||
{
|
||||
dprint("ai_run_missile: not visible\n");
|
||||
self.attack_state = AS_STRAIGHT;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (FacingIdeal(90))
|
||||
{
|
||||
if (self.attack_state == AS_SPAM)
|
||||
self.th_spam();
|
||||
else
|
||||
self.th_missile();
|
||||
self.attack_state = AS_STRAIGHT;
|
||||
}
|
||||
};
|
||||
|
||||
/*==========
|
||||
ai_run_slide
|
||||
|
||||
Face the enemy and strafe sideways
|
||||
==========*/
|
||||
void(float dist) ai_run_slide =
|
||||
{
|
||||
self.ideal_yaw = enemy_yaw;
|
||||
changeyaw();
|
||||
|
||||
float ofs;
|
||||
if (self.lefty)
|
||||
ofs = 90;
|
||||
else
|
||||
ofs = -90;
|
||||
|
||||
if (walkmove (self.ideal_yaw + ofs, dist))
|
||||
return;
|
||||
self.lefty = 1 - self.lefty;
|
||||
walkmove (self.ideal_yaw - ofs, dist);
|
||||
};
|
||||
|
||||
#define ROUTE_MAX 256
|
||||
float route_busy;
|
||||
.float route;
|
||||
.entity route_table[ROUTE_MAX];
|
||||
.float distance;
|
||||
.float route_time;
|
||||
|
||||
/*============
|
||||
ClearRoute
|
||||
|
||||
clear the monsters current route
|
||||
============*/
|
||||
void() ClearRoute =
|
||||
{
|
||||
self.route = -1;
|
||||
for (float i = 0; i < ROUTE_MAX; i = i + 1)
|
||||
self.route_table[i] = world;
|
||||
};
|
||||
|
||||
/*============
|
||||
ClearWayTable
|
||||
|
||||
clear the waypoint table (which is shared between all monsters)
|
||||
marks all waypoints as not visited and infinite distance
|
||||
============*/
|
||||
void() ClearWayTable =
|
||||
{
|
||||
entity e = way_head;
|
||||
while (e)
|
||||
{
|
||||
e.state = -1;
|
||||
e.distance = -1;
|
||||
e.last_way = world;
|
||||
e = e._next;
|
||||
}
|
||||
};
|
||||
|
||||
/*==========
|
||||
CheckDoors
|
||||
|
||||
check if a door is in the way of two waypoints while checking a route
|
||||
==========*/
|
||||
float(entity e) CheckDoors =
|
||||
{
|
||||
traceline(self.enemy.origin, e.origin, TRUE, self.enemy);
|
||||
if (trace_fraction == 1)
|
||||
return TRUE;
|
||||
if (trace_ent == e)
|
||||
return TRUE;
|
||||
|
||||
if (trace_ent.classname == "door")
|
||||
{
|
||||
// we check .owner because it's the master door
|
||||
if (trace_ent.owner.items) // key door
|
||||
return FALSE;
|
||||
if (trace_ent.owner.health) // shootable door
|
||||
return FALSE;
|
||||
if (trace_ent.owner.targetname != "") // triggered door
|
||||
return FALSE;
|
||||
|
||||
return TRUE; // regular door with a trigger field
|
||||
}
|
||||
|
||||
dprint("CheckDoors: \n");
|
||||
dprint(trace_ent.classname);
|
||||
dprint("\n");
|
||||
|
||||
return FALSE; // something else in the way
|
||||
};
|
||||
|
||||
/*==========
|
||||
CheckRoute
|
||||
|
||||
called from RouteThink to update the distances between the waypoints
|
||||
==========*/
|
||||
void(entity e) CheckRoute =
|
||||
{
|
||||
if (!e)
|
||||
return;
|
||||
if (e.state > 0)
|
||||
return;
|
||||
if (!CheckDoors(e))
|
||||
return;
|
||||
|
||||
float dist = self.enemy.distance;
|
||||
dist = dist + vlen(self.enemy.origin - e.origin);
|
||||
dist = dist + random() * 32; // add some fuzzyness
|
||||
|
||||
if ((e.distance == -1) || (dist < e.distance))
|
||||
{
|
||||
e.distance = dist;
|
||||
e.last_way = self.enemy;
|
||||
}
|
||||
};
|
||||
|
||||
/*==========
|
||||
RouteThink
|
||||
|
||||
return the shortest path to the goal waypoint
|
||||
==========*/
|
||||
void() RouteThink =
|
||||
{
|
||||
entity e;
|
||||
|
||||
// the monster died while calculating a route - free up the table
|
||||
if (self.owner.health <= 0)
|
||||
{
|
||||
route_busy = 0;
|
||||
remove(self);
|
||||
fixer = world;
|
||||
return;
|
||||
}
|
||||
|
||||
// visit all waypoints linking to current waypoint and update their distance
|
||||
CheckRoute(self.enemy.target1);
|
||||
CheckRoute(self.enemy.target2);
|
||||
CheckRoute(self.enemy.target3);
|
||||
CheckRoute(self.enemy.target4);
|
||||
|
||||
// mark this waypoint as visited
|
||||
self.enemy.state = 1;
|
||||
|
||||
// found route
|
||||
if (self.goalentity.state == 1)
|
||||
{
|
||||
//dprint("RouteThink: found route\n");
|
||||
|
||||
e = self.goalentity;
|
||||
float i = 0;
|
||||
while (e)
|
||||
{
|
||||
self.owner.route_table[i] = e;
|
||||
e = e.last_way;
|
||||
if (e) // don't count the final waypoint, as it's the one the monster is already at
|
||||
i = i + 1;
|
||||
}
|
||||
|
||||
self.owner.route = i - 1; // because route_table is a zero indexed array
|
||||
self.owner.route_time = time + 5;
|
||||
route_busy = FALSE;
|
||||
remove(self);
|
||||
fixer = world;
|
||||
return;
|
||||
}
|
||||
|
||||
// find the nearest, unvisited waypoint
|
||||
entity best = world;
|
||||
float bdist = -1;
|
||||
e = way_head;
|
||||
while (e)
|
||||
{
|
||||
if (e.state == -1) // not visited
|
||||
{
|
||||
if (e.distance > 0) // we use -1 for "infinite distance"
|
||||
{
|
||||
if (e.distance < bdist || bdist == -1)
|
||||
{
|
||||
best = e;
|
||||
bdist = e.distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
e = e._next;
|
||||
}
|
||||
|
||||
// no valid route exists between the two waypoints
|
||||
if (best == world)
|
||||
{
|
||||
//dprint("RouteThink: no valid route exists\n");
|
||||
route_busy = FALSE;
|
||||
remove(self);
|
||||
fixer = world;
|
||||
return;
|
||||
}
|
||||
|
||||
// update the next waypoint
|
||||
self.enemy = best;
|
||||
self.think = RouteThink;
|
||||
self.nextthink = time;
|
||||
};
|
||||
|
||||
/*============
|
||||
StartRoute
|
||||
|
||||
called by monsters when they want to find a path between waypoint A and B
|
||||
uses thinks to avoid tripping the runaway counter (RouteThink)
|
||||
============*/
|
||||
void(entity e1, entity e2) StartRoute =
|
||||
{
|
||||
// no waypoints exist in map
|
||||
if (!waypoints)
|
||||
return;
|
||||
// another monster is already calculating a route
|
||||
if (route_busy)
|
||||
return;
|
||||
// sanity check
|
||||
if (e1 == world || e2 == world || e1 == e2)
|
||||
return;
|
||||
|
||||
//dprint("StartRoute\n");
|
||||
|
||||
// mark the table as busy and clear it for use
|
||||
route_busy = TRUE;
|
||||
ClearWayTable();
|
||||
|
||||
// the first waypoint is always distance zero
|
||||
e1.distance = 0;
|
||||
|
||||
if (!fixer)
|
||||
fixer = spawn();
|
||||
fixer.owner = self;
|
||||
fixer.enemy = e1; // start waypoint
|
||||
fixer.goalentity = e2; // end waypoint
|
||||
fixer.nextthink = time;
|
||||
fixer.think = RouteThink;
|
||||
};
|
||||
|
||||
/*==========
|
||||
FindWaypoint
|
||||
==========*/
|
||||
entity(entity monster, entity start) FindWaypoint =
|
||||
{
|
||||
if (!waypoints)
|
||||
return world;
|
||||
|
||||
if (start != world)
|
||||
{
|
||||
float best_dist = vlen(start.origin - monster.origin);
|
||||
entity best = start;
|
||||
}
|
||||
else
|
||||
{
|
||||
best_dist = -1;
|
||||
best = world;
|
||||
}
|
||||
|
||||
if (best_dist < 20)
|
||||
return best;
|
||||
|
||||
entity w = way_head;
|
||||
while(w)
|
||||
{
|
||||
float way_dist = vlen(w.origin - monster.origin);
|
||||
if (way_dist < best_dist || best_dist == -1)
|
||||
{
|
||||
if (wisible(monster, w))
|
||||
{
|
||||
best_dist = way_dist;
|
||||
best = w;
|
||||
}
|
||||
}
|
||||
w = w._next;
|
||||
}
|
||||
|
||||
if (best_dist < 256)
|
||||
{
|
||||
//dprint("FindWaypoint: found\n");
|
||||
return best;
|
||||
}
|
||||
else
|
||||
{
|
||||
//dprint("FindWaypoint: world\n");
|
||||
return world;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
=============
|
||||
ai_run
|
||||
|
||||
The monster has an enemy it is trying to kill
|
||||
=============
|
||||
*/
|
||||
void(float dist) ai_run =
|
||||
{
|
||||
// stop all attacks during the intermission
|
||||
if (intermission_running)
|
||||
{
|
||||
ClearRoute();
|
||||
self.enemy = self.goalentity = world;
|
||||
self.th_stand();
|
||||
return;
|
||||
}
|
||||
// our enemy has died, so look for a new one
|
||||
if (self.enemy.health <= 0)
|
||||
{
|
||||
ClearRoute();
|
||||
self.enemy = self.goalentity = world;
|
||||
// look for previous enemy
|
||||
if (self.oldenemy.health > 0)
|
||||
{
|
||||
self.enemy = self.oldenemy;
|
||||
HuntTarget();
|
||||
}
|
||||
else
|
||||
{
|
||||
self.th_stand();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: get rid of globals
|
||||
enemy_vis = visible(self.enemy);
|
||||
enemy_infront = infront(self.enemy);
|
||||
enemy_range = range(self.enemy);
|
||||
enemy_yaw = vectoyaw(self.enemy.origin - self.origin);
|
||||
if (enemy_vis)
|
||||
{
|
||||
self.enemy_last = self.enemy.origin + self.enemy.view_ofs;
|
||||
self.search_time = time + 5;
|
||||
}
|
||||
|
||||
// look for other players in co-op
|
||||
if (coop && self.search_time < time)
|
||||
{
|
||||
if (FindTarget())
|
||||
return;
|
||||
}
|
||||
|
||||
// we've started an attack, so make sure we're facing the right way before launching
|
||||
if (self.attack_state == AS_MISSILE || self.attack_state == AS_SPAM)
|
||||
{
|
||||
ai_run_missile();
|
||||
return;
|
||||
}
|
||||
if (self.attack_state == AS_MELEE)
|
||||
{
|
||||
ai_run_melee();
|
||||
return;
|
||||
}
|
||||
|
||||
// check for beginning an attack
|
||||
if (CheckAnyAttack())
|
||||
return;
|
||||
|
||||
// used by scrags
|
||||
if (self.attack_state == AS_SLIDING)
|
||||
{
|
||||
ai_run_slide(dist);
|
||||
return;
|
||||
}
|
||||
|
||||
// no waypoints in map, so just use regular movement
|
||||
if (waypoint_mode < WM_LOADED || !waypoints)
|
||||
{
|
||||
ai_movetogoal(self.enemy, dist);
|
||||
return;
|
||||
}
|
||||
|
||||
// we have an enemy, but no route, so find a route to the enemy
|
||||
if (self.route < 0)
|
||||
{
|
||||
//dprint("Finding route\n");
|
||||
self.current_way = FindWaypoint(self, self.current_way);
|
||||
self.enemy.current_way = FindWaypoint(self.enemy, self.enemy.current_way);
|
||||
StartRoute(self.current_way, self.enemy.current_way);
|
||||
|
||||
ai_movetogoal(self.enemy, dist);
|
||||
return;
|
||||
}
|
||||
|
||||
// monster has failed to move to the next waypoint, so drop the route
|
||||
if (time > self.route_time)
|
||||
{
|
||||
//dprint("Dropping route\n");
|
||||
ClearRoute();
|
||||
ai_movetogoal(self.enemy, dist);
|
||||
return;
|
||||
}
|
||||
|
||||
// periodically refresh enemy waypoint
|
||||
if (!route_busy)
|
||||
{
|
||||
self.enemy.current_way = FindWaypoint(self.enemy, self.enemy.current_way);
|
||||
if (self.route_table[0] != self.enemy.current_way)
|
||||
StartRoute(self.current_way, self.enemy.current_way);
|
||||
}
|
||||
|
||||
// move to the next waypoint
|
||||
entity w = self.route_table[self.route];
|
||||
ai_movetogoal(w, dist);
|
||||
|
||||
// hit next waypoint
|
||||
if (vlen(self.origin - w.origin) < 64)
|
||||
{
|
||||
self.route_time = time + 5;
|
||||
self.current_way = self.route_table[self.route];
|
||||
self.route = self.route - 1;
|
||||
|
||||
// hit last waypoint
|
||||
if (self.route < 0)
|
||||
{
|
||||
dprint("Hit last waypoint\n");
|
||||
ClearRoute();
|
||||
}
|
||||
}
|
||||
};
|
||||
174
mod_slipgate/source/server/ambient.qc
Normal file
174
mod_slipgate/source/server/ambient.qc
Normal file
@@ -0,0 +1,174 @@
|
||||
/*==========
|
||||
spawn_ambient
|
||||
==========*/
|
||||
void(float soundnum, vector org, float vol, float atn) spawn_ambient =
|
||||
{
|
||||
WriteByte(MSG_ALL, SVC_SPAWNSTATICSOUND);
|
||||
WriteCoord(MSG_ALL, org_x);
|
||||
WriteCoord(MSG_ALL, org_y);
|
||||
WriteCoord(MSG_ALL, org_z);
|
||||
WriteByte(MSG_ALL, soundnum);
|
||||
WriteByte(MSG_ALL, vol * 255);
|
||||
WriteByte(MSG_ALL, atn * 64);
|
||||
};
|
||||
|
||||
/*==========
|
||||
ambient_start
|
||||
==========*/
|
||||
void(string s, float vol, float atn) ambient_start =
|
||||
{
|
||||
precache_sound(s);
|
||||
ambientsound(self.origin, s, vol, atn);
|
||||
};
|
||||
|
||||
/*QUAKED ambient_custom (0.3 0.1 0.6) (-8 -8 -8) (8 8 8)
|
||||
Customisable ambient sound.
|
||||
|
||||
Keys:
|
||||
"noise" - Ambient sound to play.
|
||||
"volume" - Set the volume of the sound. Range 0-1. Default 0.5.
|
||||
"distance" - Set the attenuation of the ambient sound:
|
||||
0 - static (default, usual for ambient sounds)
|
||||
1 - idle (usually used for monster idle sounds)
|
||||
2 - normal (normal attenuation)
|
||||
3 - none (no attenuation, audible throughout entire map)
|
||||
*/
|
||||
void() ambient_custom =
|
||||
{
|
||||
if (!self.noise)
|
||||
{
|
||||
objerror("no noise specified\n");
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
if (self.volume > 1)
|
||||
self.volume = 1;
|
||||
if (self.volume <= 0)
|
||||
self.volume = 0.5;
|
||||
if (self.distance < 0)
|
||||
self.distance = 0;
|
||||
if (self.distance > 3)
|
||||
self.distance = 3;
|
||||
float atn = 0;
|
||||
switch (self.distance)
|
||||
{
|
||||
case 0:
|
||||
default:
|
||||
atn = ATTN_STATIC;
|
||||
break;
|
||||
case 1:
|
||||
atn = ATTN_IDLE;
|
||||
break;
|
||||
case 2:
|
||||
atn = ATTN_NORM;
|
||||
break;
|
||||
case 3:
|
||||
atn = ATTN_NONE;
|
||||
break;
|
||||
}
|
||||
ambient_start(self.noise, self.volume, atn);
|
||||
};
|
||||
|
||||
/*QUAKED ambient_comp_hum (0.3 0.1 0.6) (-8 -8 -8) (8 8 8)
|
||||
Ambient computer hum.
|
||||
*/
|
||||
void() ambient_comp_hum =
|
||||
{
|
||||
ambient_start("ambience/comp1.wav", 0.5, ATTN_STATIC);
|
||||
};
|
||||
|
||||
/*QUAKED ambient_drip (0.3 0.1 0.6) (-8 -8 -8) (8 8 8)
|
||||
Ambient water drip.
|
||||
*/
|
||||
void() ambient_drip =
|
||||
{
|
||||
ambient_start("ambience/drip1.wav", 0.5, ATTN_STATIC);
|
||||
};
|
||||
|
||||
/*QUAKED ambient_drone (0.3 0.1 0.6) (-8 -8 -8) (8 8 8)
|
||||
Ambient drone.
|
||||
*/
|
||||
void() ambient_drone =
|
||||
{
|
||||
ambient_start("ambience/drone6.wav", 0.5, ATTN_STATIC);
|
||||
};
|
||||
|
||||
/*QUAKED ambient_fire (0.3 0.1 0.6) (-8 -8 -8) (8 8 8)
|
||||
Ambient fire crackling.
|
||||
*/
|
||||
void() ambient_fire =
|
||||
{
|
||||
ambient_start("ambience/fire1.wav", 0.5, ATTN_STATIC);
|
||||
};
|
||||
|
||||
/*QUAKED ambient_flouro_buzz (0.3 0.1 0.6) (-8 -8 -8) (8 8 8)
|
||||
Ambient flourescent light buzzing.
|
||||
*/
|
||||
void() ambient_flouro_buzz =
|
||||
{
|
||||
ambient_start("ambience/buzz1.wav", 0.5, ATTN_STATIC);
|
||||
};
|
||||
|
||||
/*QUAKED ambient_light_buzz (0.3 0.1 0.6) (-8 -8 -8) (8 8 8)
|
||||
Ambient light buzz.
|
||||
*/
|
||||
void() ambient_light_buzz =
|
||||
{
|
||||
ambient_start("ambience/fl_hum1.wav", 0.5, ATTN_STATIC);
|
||||
};
|
||||
|
||||
/*QUAKED ambient_suck_wind (0.3 0.1 0.6) (-8 -8 -8) (8 8 8)
|
||||
Ambient sucking wind.
|
||||
*/
|
||||
void() ambient_suck_wind =
|
||||
{
|
||||
ambient_start("ambience/suck1.wav", 0.5, ATTN_STATIC);
|
||||
};
|
||||
|
||||
/*QUAKED ambient_swamp1 (0.3 0.1 0.6) (-8 -8 -8) (8 8 8)
|
||||
Ambient swamp - 1st variation.
|
||||
*/
|
||||
void() ambient_swamp1 =
|
||||
{
|
||||
ambient_start("ambience/swamp1.wav", 0.5, ATTN_STATIC);
|
||||
};
|
||||
|
||||
/*QUAKED ambient_swamp2 (0.3 0.1 0.6) (-8 -8 -8) (8 8 8)
|
||||
Ambient swamp - 2nd variation.
|
||||
*/
|
||||
void() ambient_swamp2 =
|
||||
{
|
||||
ambient_start("ambience/swamp2.wav", 0.5, ATTN_STATIC);
|
||||
};
|
||||
|
||||
/*QUAKED ambient_teleport (0.3 0.1 0.6) (-8 -8 -8) (8 8 8)
|
||||
Ambient teleporter hum.
|
||||
*/
|
||||
void() ambient_teleport =
|
||||
{
|
||||
ambient_start("ambience/hum1.wav", 0.5, ATTN_STATIC);
|
||||
};
|
||||
|
||||
/*QUAKED ambient_thunder (0.3 0.1 0.6) (-8 -8 -8) (8 8 8)
|
||||
Ambient thunder.
|
||||
*/
|
||||
void() ambient_thunder =
|
||||
{
|
||||
ambient_start("ambience/thunder1.wav", 0.5, ATTN_STATIC);
|
||||
};
|
||||
|
||||
/*QUAKED ambient_water (0.3 0.1 0.6) (-8 -8 -8) (8 8 8)
|
||||
Ambient water.
|
||||
*/
|
||||
void() ambient_water =
|
||||
{
|
||||
ambient_start("ambience/water1.wav", 0.5, ATTN_STATIC);
|
||||
};
|
||||
|
||||
/*QUAKED ambient_wind (0.3 0.1 0.6) (-8 -8 -8) (8 8 8)
|
||||
Ambient wind.
|
||||
*/
|
||||
void() ambient_wind =
|
||||
{
|
||||
ambient_start("ambience/wind2.wav", 0.5, ATTN_STATIC);
|
||||
};
|
||||
84
mod_slipgate/source/server/bmodel.qc
Normal file
84
mod_slipgate/source/server/bmodel.qc
Normal file
@@ -0,0 +1,84 @@
|
||||
/*==========
|
||||
wall_use
|
||||
==========*/
|
||||
void() wall_use =
|
||||
{
|
||||
self.frame = 1 - self.frame;
|
||||
};
|
||||
|
||||
/*QUAKED func_wall (0 .5 .8) ? X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
Simple solid bmodel
|
||||
|
||||
Keys:
|
||||
"targetname" - if triggered, the bmodel will toggle its frame/animation sequence from +0 -> +9 to +a -> +j
|
||||
*/
|
||||
void() func_wall =
|
||||
{
|
||||
self.angles = '0 0 0';
|
||||
self.movetype = MOVETYPE_PUSH;
|
||||
self.solid = SOLID_BSP;
|
||||
self.use = wall_use;
|
||||
setmodel (self, self.model);
|
||||
};
|
||||
|
||||
/*QUAKED func_illusionary (0 .5 .8) ? X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
A simple bmodel that looks solid but lets the player walk through it
|
||||
|
||||
Keys:
|
||||
"targetname" - if triggered, the bmodel will toggle its frame/animation sequence from +0 -> +9 to +a -> +j
|
||||
*/
|
||||
void() func_illusionary =
|
||||
{
|
||||
self.angles = '0 0 0';
|
||||
self.movetype = MOVETYPE_NONE;
|
||||
self.solid = SOLID_NOT;
|
||||
setmodel (self, self.model);
|
||||
|
||||
if (self.targetname != "")
|
||||
self.use = wall_use;
|
||||
else
|
||||
makestatic(self);
|
||||
};
|
||||
|
||||
/*QUAKED func_episodegate (0 .5 .8) ? E1 E2 E3 E4 X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
This bmodel will only appear if the episode has already been completed.
|
||||
|
||||
Keys:
|
||||
"targetname" - if triggered, the bmodel will toggle its frame/animation sequence from +0 -> +9 to +a -> +j
|
||||
|
||||
Spawnflags:
|
||||
E1, E2, E3, E4
|
||||
*/
|
||||
void() func_episodegate =
|
||||
{
|
||||
if (!(serverflags & self.spawnflags))
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
self.angles = '0 0 0';
|
||||
self.movetype = MOVETYPE_PUSH;
|
||||
self.solid = SOLID_BSP;
|
||||
self.use = wall_use;
|
||||
setmodel (self, self.model);
|
||||
};
|
||||
|
||||
/*QUAKED func_bossgate (0 .5 .8) ? X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
This bmodel appears unless the player has all of the episode runes.
|
||||
|
||||
Keys:
|
||||
"targetname" - if triggered, the bmodel will toggle its frame/animation sequence from +0 -> +9 to +a -> +j
|
||||
*/
|
||||
void() func_bossgate =
|
||||
{
|
||||
if ((serverflags & 15) == 15)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
self.angles = '0 0 0';
|
||||
self.movetype = MOVETYPE_PUSH;
|
||||
self.solid = SOLID_BSP;
|
||||
self.use = wall_use;
|
||||
setmodel (self, self.model);
|
||||
};
|
||||
39
mod_slipgate/source/server/bodyque.qc
Normal file
39
mod_slipgate/source/server/bodyque.qc
Normal file
@@ -0,0 +1,39 @@
|
||||
entity bodyque_head;
|
||||
|
||||
void() bodyque = {};
|
||||
|
||||
void() InitBodyQue =
|
||||
{
|
||||
float count = 10;
|
||||
|
||||
bodyque_head = world;
|
||||
entity prev = world;
|
||||
entity corpse = world;
|
||||
while (count)
|
||||
{
|
||||
corpse = spawn();
|
||||
corpse.classname = "bodyque";
|
||||
if (bodyque_head == world)
|
||||
bodyque_head = corpse;
|
||||
if (prev != world)
|
||||
prev.owner = corpse;
|
||||
prev = corpse;
|
||||
count = count - 1;
|
||||
}
|
||||
corpse.owner = bodyque_head;
|
||||
};
|
||||
|
||||
void(entity ent) CopyToBodyQue =
|
||||
{
|
||||
bodyque_head.angles = ent.angles;
|
||||
bodyque_head.model = ent.model;
|
||||
bodyque_head.modelindex = ent.modelindex;
|
||||
bodyque_head.frame = ent.frame;
|
||||
bodyque_head.colormap = ent.colormap;
|
||||
bodyque_head.movetype = ent.movetype;
|
||||
bodyque_head.velocity = ent.velocity;
|
||||
bodyque_head.flags = 0;
|
||||
setorigin (bodyque_head, ent.origin);
|
||||
setsize (bodyque_head, ent.mins, ent.maxs);
|
||||
bodyque_head = bodyque_head.owner;
|
||||
};
|
||||
322
mod_slipgate/source/server/breakable.qc
Normal file
322
mod_slipgate/source/server/breakable.qc
Normal file
@@ -0,0 +1,322 @@
|
||||
static enumflags { EXPLODE, NO_EXPLOSION_SPRITE, NO_EXPLOSION_SOUND, SPAWN_SMOKE };
|
||||
|
||||
/*==========
|
||||
breakable_pain
|
||||
==========*/
|
||||
static void(entity attacker, float damage) breakable_pain =
|
||||
{
|
||||
// play impact sound if set
|
||||
if (self.noise2 != "")
|
||||
sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
|
||||
};
|
||||
|
||||
/*==========
|
||||
breakable_think
|
||||
==========*/
|
||||
static void() breakable_think =
|
||||
{
|
||||
// hack to drop to ground if something below us was removed
|
||||
if (self.flags & FL_ONGROUND)
|
||||
self.flags = self.flags - FL_ONGROUND;
|
||||
|
||||
// fade out when self.attack_finished is up
|
||||
if (time > self.attack_finished)
|
||||
{
|
||||
if (self.alpha == 0)
|
||||
self.alpha = 1;
|
||||
|
||||
self.alpha = self.alpha - 0.1;
|
||||
if (self.alpha <= 0)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.think = breakable_think;
|
||||
self.nextthink = time + 0.1;
|
||||
};
|
||||
|
||||
/*==========
|
||||
breakable_touch
|
||||
==========*/
|
||||
static void() breakable_touch =
|
||||
{
|
||||
if (other != world)
|
||||
return;
|
||||
if (self.count)
|
||||
return;
|
||||
if (random() < 0.5)
|
||||
return;
|
||||
self.count = 1;
|
||||
if (self.noise2 != "")
|
||||
sound(self, CHAN_VOICE, self.noise2, 0.5, ATTN_IDLE);
|
||||
};
|
||||
|
||||
/*==========
|
||||
breakable_smoke
|
||||
==========*/
|
||||
static void(vector org) breakable_smoke =
|
||||
{
|
||||
entity smoke = spawn();
|
||||
smoke.classname = "smoke";
|
||||
smoke.solid = SOLID_NOT;
|
||||
smoke.movetype = MOVETYPE_TOSS;
|
||||
setmodel(smoke, "progs/smoke.mdl");
|
||||
setorigin(smoke, org);
|
||||
setsize(smoke, '0 0 0', '0 0 0');
|
||||
|
||||
smoke.velocity = [crandom()*200, crandom()*200, random()*100 + 100];
|
||||
smoke.think = SUB_Remove;
|
||||
smoke.nextthink = time + 1;
|
||||
};
|
||||
|
||||
/*==========
|
||||
breakable_spawn_debris
|
||||
==========*/
|
||||
static void(vector org, vector sz, vector dir) breakable_spawn_debris =
|
||||
{
|
||||
entity debris = spawn();
|
||||
debris.classname = "debris";
|
||||
debris.solid = SOLID_TRIGGER;
|
||||
debris.movetype = MOVETYPE_BOUNCE;
|
||||
|
||||
setorigin(debris, [org.x + random() * sz.x, org.y + random() * sz.y, org.z + random() * sz.z]);
|
||||
|
||||
float r = random();
|
||||
if (r < 0.33)
|
||||
setmodel(debris, self.mdl1);
|
||||
else if (r < 0.66)
|
||||
setmodel(debris, self.mdl2);
|
||||
else
|
||||
setmodel(debris, self.mdl3);
|
||||
|
||||
// spawn some smoke particles
|
||||
if (self.spawnflags & SPAWN_SMOKE)
|
||||
if (random() < 0.5)
|
||||
breakable_smoke(debris.origin);
|
||||
|
||||
debris.angles_y = random() * 360;
|
||||
debris.velocity = dir * (50 + random() * 50);
|
||||
debris.velocity_z = 50 + random() * 50;
|
||||
if (self.health < -40)
|
||||
debris.velocity = debris.velocity * 2;
|
||||
debris.avelocity = randomvec() * 100;
|
||||
|
||||
debris.noise2 = self.noise2;
|
||||
debris.touch = breakable_touch;
|
||||
|
||||
debris.think = breakable_think;
|
||||
debris.nextthink = time + 0.1;
|
||||
debris.attack_finished = time + 10 + random() * 10;
|
||||
};
|
||||
|
||||
/*==========
|
||||
breakable_explode
|
||||
==========*/
|
||||
static void() breakable_explode =
|
||||
{
|
||||
setorigin(self, realorigin(self)); // fix bmodel origin
|
||||
|
||||
if (self.dmg > 0)
|
||||
RadiusDamage (self, self, self.dmg, world);
|
||||
|
||||
if (self.spawnflags & NO_EXPLOSION_SOUND)
|
||||
{
|
||||
// vanilla hack to get explosion particles with no sound/light
|
||||
particle (self.origin, '0 0 0', 0, 255);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_EXPLOSION);
|
||||
WriteCoord (MSG_BROADCAST, self.origin_x);
|
||||
WriteCoord (MSG_BROADCAST, self.origin_y);
|
||||
WriteCoord (MSG_BROADCAST, self.origin_z);
|
||||
}
|
||||
|
||||
if (self.spawnflags & NO_EXPLOSION_SPRITE)
|
||||
remove(self);
|
||||
else
|
||||
BecomeExplosion ();
|
||||
};
|
||||
|
||||
/*==========
|
||||
breakable_break
|
||||
==========*/
|
||||
static void(entity inflictor) breakable_break =
|
||||
{
|
||||
self.takedamage = DAMAGE_NO;
|
||||
self.use = SUB_Null;
|
||||
|
||||
// play sound, if set
|
||||
if (self.noise1 != "")
|
||||
sound(self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
|
||||
|
||||
// turn shadow off, supported by ericw-tools
|
||||
if (self.switchshadstyle >= 32)
|
||||
lightstyle(self.switchshadstyle, "m");
|
||||
|
||||
// the debris moves away from the direction of attack
|
||||
// if movedir is set, this always overrides the direction
|
||||
while (self.count > 0)
|
||||
{
|
||||
vector dir;
|
||||
if (self.movedir)
|
||||
dir = self.movedir;
|
||||
else
|
||||
{
|
||||
if (inflictor == world)
|
||||
dir = randomvec();
|
||||
else
|
||||
dir = normalize((self.absmin + self.absmax) * 0.5 - inflictor.origin);
|
||||
}
|
||||
breakable_spawn_debris(self.absmin, self.size, dir);
|
||||
self.count = self.count - 1;
|
||||
}
|
||||
|
||||
if (self.spawnflags & EXPLODE)
|
||||
self.think = breakable_explode;
|
||||
else
|
||||
self.think = SUB_Remove;
|
||||
self.nextthink = self.ltime + 0.01; // use ltime because it's MOVETYPE_PUSH
|
||||
|
||||
// fire targets
|
||||
activator = self.enemy;
|
||||
UseTargets();
|
||||
};
|
||||
|
||||
/*==========
|
||||
breakable_die
|
||||
==========*/
|
||||
static void(entity inflictor, entity attacker) breakable_die =
|
||||
{
|
||||
self.enemy = attacker;
|
||||
breakable_break(inflictor);
|
||||
};
|
||||
|
||||
/*==========
|
||||
breakable_use
|
||||
==========*/
|
||||
static void() breakable_use =
|
||||
{
|
||||
self.enemy = activator;
|
||||
breakable_break(world);
|
||||
};
|
||||
|
||||
/*QUAKED func_breakable (0 .5 .8) ? EXPLODE NO_EXPLOSION_SPRITE NO_EXPLOSION_SOUND SPAWN_SMOKE X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
Breakable brush model
|
||||
|
||||
Spawnflags:
|
||||
EXPLODE - will explode upon destruction. Set the dmg key to the force of the explosion.
|
||||
You can set dmg to 0 for just the explosion effects.
|
||||
NO_EXPLOSION_SPRITE - don't show explosion sprite.
|
||||
NO_EXPLOSION_SOUND - don't make explosion sound or light.
|
||||
SPAWN_SMOKE - will spawn some additional smoke upon destuction
|
||||
|
||||
Keys:
|
||||
"style" "n"
|
||||
Preset style, 1=base crates, 2=stone/brick
|
||||
Sets debris model, particle color and sounds automatically
|
||||
If mdl1-3, noise or colour are set they will override the preset
|
||||
|
||||
"mdl1", "mdl2", "mdl3" "name"
|
||||
custom models for debris chunks
|
||||
|
||||
"color" "n"
|
||||
particle color for damage, range 0-254 (from palette)
|
||||
|
||||
"noise1", "noise2" "name"
|
||||
custom sound for break / damage
|
||||
|
||||
"health" "n"
|
||||
damage required to destroy. default 30.
|
||||
|
||||
"targetname" "name"
|
||||
if set, the breakable must be triggered to destroy it
|
||||
|
||||
"count" "n"
|
||||
number of pieces of debris to spawn. default 8.
|
||||
|
||||
"angle" "n"
|
||||
If set, overrides the direction debris moves in. Use -1 and -2 for up/down. Use 360 for a yaw of 0.
|
||||
|
||||
"dmg" "n"
|
||||
Amount of explosive damage to deal. Default 60.
|
||||
*/
|
||||
void() func_breakable =
|
||||
{
|
||||
// turn shadow on, supported by ericw-tools
|
||||
if (self.switchshadstyle >= 32)
|
||||
lightstyle(self.switchshadstyle, "a");
|
||||
|
||||
// pre-set styles
|
||||
// 1 - base crate
|
||||
if (self.style == 1)
|
||||
{
|
||||
if (!self.mdl1)
|
||||
self.mdl1 = "maps/crate1.bsp";
|
||||
if (!self.mdl2)
|
||||
self.mdl2 = "maps/crate2.bsp";
|
||||
if (!self.mdl3)
|
||||
self.mdl3 = "maps/crate3.bsp";
|
||||
if (!self.noise1)
|
||||
self.noise1 = "break/metbrk.wav";
|
||||
if (!self.noise2)
|
||||
self.noise2 = "break/methit.wav";
|
||||
if (!self.colour)
|
||||
self.colour = 24;
|
||||
}
|
||||
// 2 - stone/brick
|
||||
else if (self.style == 2)
|
||||
{
|
||||
if (!self.mdl1)
|
||||
self.mdl1 = "maps/brick1.bsp";
|
||||
if (!self.mdl2)
|
||||
self.mdl2 = "maps/brick2.bsp";
|
||||
if (!self.mdl3)
|
||||
self.mdl3 = "maps/brick3.bsp";
|
||||
if (!self.noise1)
|
||||
self.noise1 = "break/stonebrk.wav";
|
||||
if (!self.noise2)
|
||||
self.noise2 = "break/stonehit.wav";
|
||||
if (!self.colour)
|
||||
self.colour = 16;
|
||||
}
|
||||
|
||||
if (!self.mdl1 || !self.mdl2 || !self.mdl3)
|
||||
{
|
||||
objerror("mdl1, mdl2 or mdl3 not set\n");
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
precache_model(self.mdl1);
|
||||
precache_model(self.mdl2);
|
||||
precache_model(self.mdl3);
|
||||
|
||||
// destruction and impact noises - optional
|
||||
if (self.noise1 != "")
|
||||
precache_sound(self.noise1);
|
||||
if (self.noise2 != "")
|
||||
precache_sound(self.noise2);
|
||||
|
||||
SetPositiveDefault(count, 8);
|
||||
SetPositiveDefault(dmg, 8);
|
||||
if (self.angles)
|
||||
SetMovedir();
|
||||
|
||||
self.movetype = MOVETYPE_PUSH;
|
||||
self.solid = SOLID_BSP;
|
||||
setmodel (self, self.model);
|
||||
|
||||
// shootable, not triggered
|
||||
if (!self.targetname)
|
||||
{
|
||||
SetPositiveDefault(health, 30);
|
||||
self.takedamage = DAMAGE_YES;
|
||||
self.th_pain = breakable_pain;
|
||||
self.th_die = breakable_die;
|
||||
}
|
||||
else
|
||||
self.use = breakable_use;
|
||||
};
|
||||
111
mod_slipgate/source/server/bubbles.qc
Normal file
111
mod_slipgate/source/server/bubbles.qc
Normal file
@@ -0,0 +1,111 @@
|
||||
void() make_bubbles;
|
||||
void() bubble_remove;
|
||||
void() bubble_bob;
|
||||
|
||||
/*QUAKED air_bubbles (0 .5 .8) (-8 -8 -8) (8 8 8)
|
||||
|
||||
testing air bubbles
|
||||
*/
|
||||
|
||||
void() air_bubbles =
|
||||
|
||||
{
|
||||
if (deathmatch)
|
||||
{
|
||||
remove (self);
|
||||
return;
|
||||
}
|
||||
precache_model ("progs/s_bubble.spr");
|
||||
self.nextthink = time + 1;
|
||||
self.think = make_bubbles;
|
||||
};
|
||||
|
||||
void() make_bubbles =
|
||||
{
|
||||
local entity bubble;
|
||||
|
||||
bubble = spawn();
|
||||
setmodel (bubble, "progs/s_bubble.spr");
|
||||
setorigin (bubble, self.origin);
|
||||
bubble.movetype = MOVETYPE_NOCLIP;
|
||||
bubble.solid = SOLID_NOT;
|
||||
bubble.velocity = '0 0 15';
|
||||
bubble.nextthink = time + 0.5;
|
||||
bubble.think = bubble_bob;
|
||||
bubble.touch = bubble_remove;
|
||||
bubble.classname = "bubble";
|
||||
bubble.frame = 0;
|
||||
bubble.cnt = 0;
|
||||
setsize (bubble, '-8 -8 -8', '8 8 8');
|
||||
self.nextthink = time + random() + 0.5;
|
||||
self.think = make_bubbles;
|
||||
};
|
||||
|
||||
void() bubble_split =
|
||||
{
|
||||
local entity bubble;
|
||||
bubble = spawn();
|
||||
setmodel (bubble, "progs/s_bubble.spr");
|
||||
setorigin (bubble, self.origin);
|
||||
bubble.movetype = MOVETYPE_NOCLIP;
|
||||
bubble.solid = SOLID_NOT;
|
||||
bubble.velocity = self.velocity;
|
||||
bubble.nextthink = time + 0.5;
|
||||
bubble.think = bubble_bob;
|
||||
bubble.touch = bubble_remove;
|
||||
bubble.classname = "bubble";
|
||||
bubble.frame = 1;
|
||||
bubble.cnt = 10;
|
||||
setsize (bubble, '-8 -8 -8', '8 8 8');
|
||||
self.frame = 1;
|
||||
self.cnt = 10;
|
||||
if (self.waterlevel != 3)
|
||||
remove (self);
|
||||
};
|
||||
|
||||
void() bubble_remove =
|
||||
{
|
||||
if (other.classname == self.classname)
|
||||
{
|
||||
// dprint ("bump");
|
||||
return;
|
||||
}
|
||||
remove(self);
|
||||
};
|
||||
|
||||
void() bubble_bob =
|
||||
{
|
||||
local float rnd1, rnd2, rnd3;
|
||||
|
||||
self.cnt = self.cnt + 1;
|
||||
if (self.cnt == 4)
|
||||
bubble_split();
|
||||
if (self.cnt == 20)
|
||||
remove(self);
|
||||
|
||||
rnd1 = self.velocity_x + (-10 + (random() * 20));
|
||||
rnd2 = self.velocity_y + (-10 + (random() * 20));
|
||||
rnd3 = self.velocity_z + 10 + random() * 10;
|
||||
|
||||
if (rnd1 > 10)
|
||||
rnd1 = 5;
|
||||
if (rnd1 < -10)
|
||||
rnd1 = -5;
|
||||
|
||||
if (rnd2 > 10)
|
||||
rnd2 = 5;
|
||||
if (rnd2 < -10)
|
||||
rnd2 = -5;
|
||||
|
||||
if (rnd3 < 10)
|
||||
rnd3 = 15;
|
||||
if (rnd3 > 30)
|
||||
rnd3 = 25;
|
||||
|
||||
self.velocity_x = rnd1;
|
||||
self.velocity_y = rnd2;
|
||||
self.velocity_z = rnd3;
|
||||
|
||||
self.nextthink = time + 0.5;
|
||||
self.think = bubble_bob;
|
||||
};
|
||||
239
mod_slipgate/source/server/buttons.qc
Normal file
239
mod_slipgate/source/server/buttons.qc
Normal file
@@ -0,0 +1,239 @@
|
||||
static enumflags { BUTTON_START_OFF };
|
||||
|
||||
/*==========
|
||||
button_done
|
||||
|
||||
the button is back in its original position
|
||||
==========*/
|
||||
static void() button_done =
|
||||
{
|
||||
self.state = STATE_BOTTOM;
|
||||
};
|
||||
|
||||
/*==========
|
||||
button_return
|
||||
|
||||
the button starts to return to its original position
|
||||
==========*/
|
||||
static void() button_return =
|
||||
{
|
||||
self.state = STATE_DOWN;
|
||||
// use normal textures
|
||||
self.frame = 0;
|
||||
// can be shot again
|
||||
if (self.max_health)
|
||||
{
|
||||
self.health = self.max_health;
|
||||
self.takedamage = DAMAGE_YES;
|
||||
}
|
||||
SUB_CalcMove (self.pos1, self.speed, button_done);
|
||||
};
|
||||
|
||||
/*==========
|
||||
button_wait
|
||||
|
||||
the button has reached it's secondary position
|
||||
==========*/
|
||||
static void() button_wait =
|
||||
{
|
||||
self.state = STATE_TOP;
|
||||
// use alternatve textures
|
||||
self.frame = 1;
|
||||
// fire targets
|
||||
activator = self.enemy;
|
||||
UseTargets();
|
||||
|
||||
// return after a delay of self.wait
|
||||
if (self.wait > 0)
|
||||
{
|
||||
self.think = button_return;
|
||||
self.nextthink = self.ltime + self.wait;
|
||||
}
|
||||
// never return
|
||||
else
|
||||
{
|
||||
self.think = SUB_Null;
|
||||
self.nextthink = -1;
|
||||
}
|
||||
};
|
||||
|
||||
/*==========
|
||||
button_fire
|
||||
|
||||
the button has been activated by trigger, touch or damage
|
||||
==========*/
|
||||
static void() button_fire =
|
||||
{
|
||||
// already activated
|
||||
if (self.state == STATE_UP || self.state == STATE_TOP)
|
||||
return;
|
||||
|
||||
sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
|
||||
self.state = STATE_UP;
|
||||
SUB_CalcMove (self.pos2, self.speed, button_wait);
|
||||
};
|
||||
|
||||
/*==========
|
||||
button_touch
|
||||
==========*/
|
||||
static void() button_touch =
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
if (other.health <= 0)
|
||||
return;
|
||||
|
||||
self.enemy = other;
|
||||
button_fire ();
|
||||
};
|
||||
|
||||
/*==========
|
||||
button_killed
|
||||
|
||||
the button has been shot
|
||||
==========*/
|
||||
static void(entity inflictor, entity attacker) button_killed =
|
||||
{
|
||||
self.takedamage = DAMAGE_NO; // will be restored upon return
|
||||
self.enemy = attacker;
|
||||
button_fire();
|
||||
};
|
||||
|
||||
/*==========
|
||||
button_activate
|
||||
|
||||
enable the button for pushing or shooting
|
||||
==========*/
|
||||
static void() button_activate =
|
||||
{
|
||||
// use normal texture
|
||||
self.frame = 0;
|
||||
|
||||
// shootable button
|
||||
if (self.health > 0)
|
||||
{
|
||||
self.max_health = self.health;
|
||||
self.takedamage = DAMAGE_YES;
|
||||
self.th_die = button_killed;
|
||||
}
|
||||
// pushable button
|
||||
else
|
||||
self.touch = button_touch;
|
||||
};
|
||||
|
||||
/*==========
|
||||
button_use
|
||||
|
||||
the button has been triggered
|
||||
==========*/
|
||||
static void() button_use =
|
||||
{
|
||||
// if the button starts disabled, using it enables it
|
||||
if (self.spawnflags & BUTTON_START_OFF)
|
||||
{
|
||||
self.spawnflags = self.spawnflags - BUTTON_START_OFF;
|
||||
button_activate();
|
||||
return;
|
||||
}
|
||||
|
||||
self.enemy = activator;
|
||||
button_fire();
|
||||
};
|
||||
|
||||
/*==========
|
||||
button_blocked
|
||||
|
||||
do nothing
|
||||
==========*/
|
||||
static void() button_blocked =
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
/*QUAKED func_button (0 .5 .8) ? START_OFF X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
A button that can either be pushed or shot.
|
||||
|
||||
When a button is activated, it moves the distance of its size,
|
||||
in the direction of its angle, leaving a "lip" at the end of the move.
|
||||
Alternatively, you can specify a set "distance" to move.
|
||||
|
||||
When the move is completed, it triggers all of its targets, waits some time,
|
||||
then returns to its original position where it can be pushed or shot again.
|
||||
|
||||
Spawnflags:
|
||||
START_OFF - the button starts in a disabled state, and it must be triggered to enable it.
|
||||
Once enabled, it acts like any other button.
|
||||
|
||||
Keys:
|
||||
"target" - entities with a matching targetname will be triggered.
|
||||
"killtarget" - entities with a matching targetname will be removed.
|
||||
"targetname" - if triggered, the button will fire, unless it's already in motion
|
||||
or switched off. if switched off, it will enable itself.
|
||||
"message" - message to print to player on activation.
|
||||
"delay" - button will wait some time before triggering its targets.
|
||||
"angle" - direction of movement. use -1 for up and -2 for down.
|
||||
"speed" - speed of movement. default 40.
|
||||
"wait" - wait before returning. default 1 second. use -1 to never return.
|
||||
"lip" - number of units to leave at end of the move. default 4.
|
||||
"distance" - manually specify the distance to move, ignoring the size and lip
|
||||
"health" - if set, the button must be shot rather than pushed.
|
||||
"sounds" -
|
||||
-1) custom sound
|
||||
0) steam metal
|
||||
1) wooden clunk
|
||||
2) metallic click
|
||||
3) in-out
|
||||
"noise" - custom sound to use for button activation
|
||||
*/
|
||||
void() func_button =
|
||||
{
|
||||
if (self.sounds == 0)
|
||||
self.noise = "buttons/airbut1.wav";
|
||||
else if (self.sounds == 1)
|
||||
self.noise = "buttons/switch21.wav";
|
||||
else if (self.sounds == 2)
|
||||
self.noise = "buttons/switch02.wav";
|
||||
else if (self.sounds == 3)
|
||||
self.noise = "buttons/switch04.wav";
|
||||
if (!self.noise)
|
||||
{
|
||||
objerror("noise must be set for custom sound\n");
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
precache_sound (self.noise);
|
||||
|
||||
SetPositiveDefault(health, 0);
|
||||
SetPositiveDefault(speed, 40);
|
||||
SetFloatDefault(wait, 1);
|
||||
SetFloatDefault(lip, 4);
|
||||
self.colour = 192;
|
||||
|
||||
self.movetype = MOVETYPE_PUSH;
|
||||
self.solid = SOLID_BSP;
|
||||
setmodel (self, self.model);
|
||||
|
||||
// calculate starting and secondary position
|
||||
SetMovedir();
|
||||
self.state = STATE_BOTTOM;
|
||||
self.pos1 = self.origin;
|
||||
if (self.distance > 0)
|
||||
self.pos2 = self.pos1 + (self.movedir * self.distance);
|
||||
else
|
||||
self.pos2 = self.pos1 + self.movedir * (fabs(self.movedir*self.size) - self.lip);
|
||||
|
||||
self.blocked = button_blocked;
|
||||
self.use = button_use;
|
||||
|
||||
if (self.spawnflags & BUTTON_START_OFF)
|
||||
{
|
||||
dprint("potential button with erroneous spawnflag at ");
|
||||
dprint(vtos(realorigin(self)));
|
||||
dprint("\n");
|
||||
|
||||
self.frame = 1; // use alternative texture
|
||||
return;
|
||||
}
|
||||
|
||||
button_activate();
|
||||
};
|
||||
962
mod_slipgate/source/server/client.qc
Normal file
962
mod_slipgate/source/server/client.qc
Normal file
@@ -0,0 +1,962 @@
|
||||
|
||||
// prototypes
|
||||
void(entity attacker, float damage) player_pain;
|
||||
void() player_stand;
|
||||
void (vector org) spawn_tfog;
|
||||
void (vector org, entity death_owner) spawn_tdeath;
|
||||
|
||||
float modelindex_eyes, modelindex_player;
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
LEVEL CHANGING / INTERMISSION
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
|
||||
void() SetChangeParms =
|
||||
{
|
||||
// player was dead during the intermission
|
||||
if (self.health <= 0)
|
||||
{
|
||||
SetNewParms();
|
||||
return;
|
||||
}
|
||||
|
||||
// items
|
||||
// remove powerups and keys
|
||||
self.items = self.items - (self.items &
|
||||
(IT_SUPERHEALTH | IT_KEY1 | IT_KEY2 | IT_INVISIBILITY | IT_INVULNERABILITY | IT_SUIT | IT_QUAD));
|
||||
parm1 = self.items;
|
||||
|
||||
// cap super health
|
||||
if (self.health > 100)
|
||||
self.health = 100;
|
||||
if (self.health < 50)
|
||||
self.health = 50;
|
||||
parm2 = self.health;
|
||||
|
||||
// weapons and ammo
|
||||
parm3 = self.weapon;
|
||||
if (self.ammo_shells < 25)
|
||||
self.ammo_shells = 25;
|
||||
parm4 = self.ammo_shells;
|
||||
parm5 = self.ammo_nails;
|
||||
parm6 = self.ammo_rockets;
|
||||
parm7 = self.ammo_cells;
|
||||
|
||||
// armor
|
||||
parm8 = self.armorvalue;
|
||||
parm9 = self.armortype;
|
||||
};
|
||||
|
||||
void() SetNewParms =
|
||||
{
|
||||
parm1 = IT_AXE | IT_SHOTGUN; // items
|
||||
parm2 = 100; // health
|
||||
parm3 = IT_SHOTGUN; // weapon
|
||||
parm4 = 25; // shells
|
||||
parm5 = 0; // nails
|
||||
parm6 = 0; // rockets
|
||||
parm7 = 0; // cells
|
||||
parm8 = 0; // armorvalue
|
||||
parm9 = 0; // armortype
|
||||
};
|
||||
|
||||
void() DecodeLevelParms =
|
||||
{
|
||||
// take away all items on starting a new episode
|
||||
if ((!deathmatch) && (mapname == "start"))
|
||||
SetNewParms();
|
||||
|
||||
self.items = parm1;
|
||||
self.health = parm2;
|
||||
self.weapon = parm3;
|
||||
self.ammo_shells = parm4;
|
||||
self.ammo_nails = parm5;
|
||||
self.ammo_rockets = parm6;
|
||||
self.ammo_cells = parm7;
|
||||
self.armorvalue = parm8;
|
||||
self.armortype = parm9;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
PLAYER GAME EDGE FUNCTIONS
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
// called by ClientKill and DeadThink
|
||||
void() respawn =
|
||||
{
|
||||
if (coop)
|
||||
{
|
||||
// make a copy of the dead body for appearances sake
|
||||
CopyToBodyQue (self);
|
||||
// get the spawn parms as they were at level start
|
||||
setspawnparms (self);
|
||||
// respawn
|
||||
PutClientInServer ();
|
||||
}
|
||||
else if (deathmatch)
|
||||
{
|
||||
// make a copy of the dead body for appearances sake
|
||||
CopyToBodyQue (self);
|
||||
// set default spawn parms
|
||||
SetNewParms ();
|
||||
// respawn
|
||||
PutClientInServer ();
|
||||
}
|
||||
else
|
||||
{ // restart the entire server
|
||||
localcmd ("restart\n");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
ClientKill
|
||||
|
||||
Player entered the suicide command
|
||||
============
|
||||
*/
|
||||
void() ClientKill =
|
||||
{
|
||||
// don't allow suicide during the intermission
|
||||
// the engine aleady blocks it when dead
|
||||
if (intermission_running)
|
||||
return;
|
||||
|
||||
/*
|
||||
bprint (self.netname);
|
||||
bprint (" suicides\n");
|
||||
*/
|
||||
|
||||
self.frags = self.frags - 1; // extra penalty
|
||||
self.health = 0;
|
||||
Killed(self, self, self);
|
||||
};
|
||||
|
||||
/*
|
||||
============
|
||||
SelectSpawnPoint
|
||||
|
||||
Returns the entity to spawn at
|
||||
============
|
||||
*/
|
||||
entity() SelectSpawnPoint =
|
||||
{
|
||||
local entity spot;
|
||||
local entity thing;
|
||||
local float pcount;
|
||||
|
||||
if (developer)
|
||||
{
|
||||
spot = find (world, classname, "info_player_test");
|
||||
if (spot)
|
||||
return spot;
|
||||
}
|
||||
|
||||
if (coop)
|
||||
{
|
||||
lastspawn = find(lastspawn, classname, "info_player_coop");
|
||||
if (lastspawn == world)
|
||||
lastspawn = find (lastspawn, classname, "info_player_start");
|
||||
if (lastspawn != world)
|
||||
return lastspawn;
|
||||
}
|
||||
else if (deathmatch)
|
||||
{
|
||||
spot = lastspawn;
|
||||
while (1)
|
||||
{
|
||||
spot = find(spot, classname, "info_player_deathmatch");
|
||||
if (spot)
|
||||
{
|
||||
if (spot == lastspawn)
|
||||
return lastspawn;
|
||||
pcount = 0;
|
||||
thing = findradius(spot.origin, 32);
|
||||
while(thing)
|
||||
{
|
||||
if (thing.classname == "player")
|
||||
pcount = pcount + 1;
|
||||
thing = thing.chain;
|
||||
}
|
||||
if (pcount == 0)
|
||||
{
|
||||
lastspawn = spot;
|
||||
return spot;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
spot = find (world, classname, "info_player_start");
|
||||
if (!spot)
|
||||
error ("PutClientInServer: no info_player_start on level");
|
||||
return spot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serverflags)
|
||||
{ // return with a rune to start
|
||||
spot = find (world, classname, "info_player_start2");
|
||||
if (spot)
|
||||
return spot;
|
||||
}
|
||||
|
||||
spot = find (world, classname, "info_player_start");
|
||||
if (!spot)
|
||||
error ("PutClientInServer: no info_player_start on level");
|
||||
|
||||
return spot;
|
||||
};
|
||||
|
||||
/*
|
||||
===========
|
||||
PutClientInServer
|
||||
|
||||
called each time a player is spawned
|
||||
============
|
||||
*/
|
||||
void() DecodeLevelParms;
|
||||
void(entity inflictor, entity attacker) PlayerDie;
|
||||
|
||||
/*
|
||||
void() PutClientInServer =
|
||||
{
|
||||
self.classname = "player";
|
||||
self.health = 100;
|
||||
self.solid = SOLID_NOT;
|
||||
self.movetype = MOVETYPE_NONE;
|
||||
|
||||
entity spot = SelectSpawnPoint ();
|
||||
self.origin = self.oldorigin = spot.origin + '0 0 128';
|
||||
self.angles = [0, -90, 0];
|
||||
self.fixangle = TRUE;
|
||||
|
||||
setmodel (self, "progs/s_null.spr");
|
||||
setsize (self, [0, 0, 0], [0, 0, 0]);
|
||||
};
|
||||
*/
|
||||
|
||||
void() PutClientInServer =
|
||||
{
|
||||
self.classname = "player";
|
||||
self.health = self.max_health = 100;
|
||||
self.headmodel = "progs/h_player.mdl";
|
||||
self.deadflag = DEAD_NO;
|
||||
self.takedamage = DAMAGE_AIM;
|
||||
self.solid = SOLID_SLIDEBOX;
|
||||
self.movetype = MOVETYPE_WALK;
|
||||
self.flags = FL_CLIENT;
|
||||
self.th_pain = player_pain;
|
||||
self.th_die = PlayerDie;
|
||||
self.view_ofs = '0 0 22';
|
||||
|
||||
// liquid stuff
|
||||
self.air_finished = time + 12;
|
||||
self.dmg = 2;
|
||||
|
||||
// powerups
|
||||
self.effects = 0;
|
||||
self.super_damage_finished = 0;
|
||||
self.radsuit_finished = 0;
|
||||
self.invisible_finished = 0;
|
||||
self.invincible_finished = 0;
|
||||
self.invincible_time = 0;
|
||||
|
||||
// get items from parms and update weapon
|
||||
DecodeLevelParms();
|
||||
W_UpdateWeapon(self);
|
||||
self.show_hostile = 0;
|
||||
self.attack_finished = time;
|
||||
|
||||
// put the player on the spawn spot
|
||||
entity spot = SelectSpawnPoint ();
|
||||
self.origin = self.oldorigin = spot.origin + '0 0 1';
|
||||
self.angles = spot.angles;
|
||||
self.fixangle = TRUE;
|
||||
self.pausetime = 0;
|
||||
self.velocity = '0 0 0';
|
||||
|
||||
setmodel (self, "progs/eyes.mdl");
|
||||
modelindex_eyes = self.modelindex;
|
||||
setmodel (self, "progs/player.mdl");
|
||||
modelindex_player = self.modelindex;
|
||||
setsize (self, VEC_HULL_MIN, VEC_HULL_MAX);
|
||||
|
||||
player_stand();
|
||||
if (deathmatch || coop)
|
||||
{
|
||||
makevectors(self.angles);
|
||||
spawn_tfog (self.origin + v_forward*20);
|
||||
}
|
||||
spawn_tdeath (self.origin, self);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
RULES
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
go to the next level for deathmatch
|
||||
only called if a time or frag limit has expired
|
||||
*/
|
||||
void() NextLevel =
|
||||
{
|
||||
local entity o;
|
||||
|
||||
if (mapname == "start")
|
||||
{
|
||||
if (!cvar("registered"))
|
||||
{
|
||||
mapname = "e1m1";
|
||||
}
|
||||
else if (!(serverflags & 1))
|
||||
{
|
||||
mapname = "e1m1";
|
||||
serverflags = serverflags | 1;
|
||||
}
|
||||
else if (!(serverflags & 2))
|
||||
{
|
||||
mapname = "e2m1";
|
||||
serverflags = serverflags | 2;
|
||||
}
|
||||
else if (!(serverflags & 4))
|
||||
{
|
||||
mapname = "e3m1";
|
||||
serverflags = serverflags | 4;
|
||||
}
|
||||
else if (!(serverflags & 8))
|
||||
{
|
||||
mapname = "e4m1";
|
||||
serverflags = serverflags - 7;
|
||||
}
|
||||
|
||||
o = spawn();
|
||||
o.map = mapname;
|
||||
}
|
||||
else
|
||||
{
|
||||
// find a trigger changelevel
|
||||
o = find(world, classname, "trigger_changelevel");
|
||||
|
||||
// go back to start if no trigger_changelevel
|
||||
if (!o)
|
||||
{
|
||||
mapname = "start";
|
||||
o = spawn();
|
||||
o.map = mapname;
|
||||
}
|
||||
}
|
||||
|
||||
nextmap = o.map;
|
||||
gameover = TRUE;
|
||||
|
||||
if (o.nextthink < time)
|
||||
{
|
||||
o.think = StartIntermission;
|
||||
o.nextthink = time + 0.1;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
============
|
||||
CheckRules
|
||||
|
||||
Exit deathmatch games upon conditions
|
||||
============
|
||||
*/
|
||||
void() CheckRules =
|
||||
{
|
||||
local float timelimit;
|
||||
local float fraglimit;
|
||||
|
||||
if (gameover) // someone else quit the game already
|
||||
return;
|
||||
|
||||
timelimit = cvar("timelimit") * 60;
|
||||
fraglimit = cvar("fraglimit");
|
||||
|
||||
if (timelimit && time >= timelimit)
|
||||
{
|
||||
NextLevel ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (fraglimit && self.frags >= fraglimit)
|
||||
{
|
||||
NextLevel ();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
void() PlayerDeathThink =
|
||||
{
|
||||
if (self.deadflag == DEAD_DYING)
|
||||
return;
|
||||
|
||||
// come to a stop
|
||||
if (self.flags & FL_ONGROUND)
|
||||
{
|
||||
float forward = vlen(self.velocity);
|
||||
forward = forward - 20;
|
||||
if (forward <= 0)
|
||||
self.velocity = '0 0 0';
|
||||
else
|
||||
self.velocity = forward * normalize(self.velocity);
|
||||
}
|
||||
|
||||
// wait for button down
|
||||
if (self.deadflag == DEAD_DEAD)
|
||||
{
|
||||
if (self.button0 || self.button2)
|
||||
self.deadflag = DEAD_RESPAWNABLE;
|
||||
return;
|
||||
}
|
||||
|
||||
// wait for button release
|
||||
if (!self.button0 && !self.button2)
|
||||
respawn();
|
||||
};
|
||||
|
||||
|
||||
void() PlayerJump =
|
||||
{
|
||||
if (self.flags & FL_WATERJUMP)
|
||||
return;
|
||||
|
||||
if (self.waterlevel >= 2)
|
||||
{
|
||||
if (self.watertype == CONTENT_WATER)
|
||||
self.velocity_z = 100;
|
||||
else if (self.watertype == CONTENT_SLIME)
|
||||
self.velocity_z = 80;
|
||||
else
|
||||
self.velocity_z = 50;
|
||||
|
||||
// play swiming sound
|
||||
if (self.swim_flag < time)
|
||||
{
|
||||
self.swim_flag = time + 1;
|
||||
if (random() < 0.5)
|
||||
sound (self, CHAN_BODY, "misc/water1.wav", 1, ATTN_NORM);
|
||||
else
|
||||
sound (self, CHAN_BODY, "misc/water2.wav", 1, ATTN_NORM);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(self.flags & FL_ONGROUND))
|
||||
return;
|
||||
|
||||
if ( !(self.flags & FL_JUMPRELEASED) )
|
||||
return; // don't pogo stick
|
||||
|
||||
self.flags = self.flags - (self.flags & FL_JUMPRELEASED);
|
||||
|
||||
self.flags = self.flags - FL_ONGROUND; // don't stairwalk
|
||||
|
||||
self.button2 = 0;
|
||||
// player jumping sound
|
||||
sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
|
||||
self.velocity_z = self.velocity_z + 270;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
WaterMove
|
||||
|
||||
============
|
||||
*/
|
||||
.float dmgtime;
|
||||
|
||||
|
||||
void() CheckWaterJump =
|
||||
{
|
||||
local vector start, end;
|
||||
|
||||
// check for a jump-out-of-water
|
||||
makevectors (self.angles);
|
||||
start = self.origin;
|
||||
start_z = start_z + 8;
|
||||
v_forward_z = 0;
|
||||
normalize(v_forward);
|
||||
end = start + v_forward*24;
|
||||
traceline (start, end, TRUE, self);
|
||||
if (trace_fraction < 1)
|
||||
{ // solid at waist
|
||||
start_z = start_z + self.maxs_z - 8;
|
||||
end = start + v_forward*24;
|
||||
self.movedir = trace_plane_normal * -50;
|
||||
traceline (start, end, TRUE, self);
|
||||
if (trace_fraction == 1)
|
||||
{ // open at eye level
|
||||
self.flags = self.flags | FL_WATERJUMP;
|
||||
self.velocity_z = 225;
|
||||
self.flags = self.flags - (self.flags & FL_JUMPRELEASED);
|
||||
self.teleport_time = time + 2; // safety net
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void() WaterMove =
|
||||
{
|
||||
// don't drown if no clip...
|
||||
if (self.movetype == MOVETYPE_NOCLIP)
|
||||
{
|
||||
self.air_finished = time + 12;
|
||||
self.dmg = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.waterlevel == 2)
|
||||
CheckWaterJump ();
|
||||
|
||||
if (self.waterlevel != 3)
|
||||
{
|
||||
if (self.air_finished < time)
|
||||
sound (self, CHAN_VOICE, "player/gasp2.wav", 1, ATTN_NORM);
|
||||
else if (self.air_finished < time + 9)
|
||||
sound (self, CHAN_VOICE, "player/gasp1.wav", 1, ATTN_NORM);
|
||||
self.air_finished = time + 12;
|
||||
self.dmg = 2;
|
||||
}
|
||||
else if (self.air_finished < time)
|
||||
{ // drown!
|
||||
if (self.pain_finished < time)
|
||||
{
|
||||
self.dmg = self.dmg + 2;
|
||||
if (self.dmg > 15)
|
||||
self.dmg = 10;
|
||||
Damage (self, world, world, self.dmg);
|
||||
self.pain_finished = time + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!self.waterlevel)
|
||||
{
|
||||
if (self.flags & FL_INWATER)
|
||||
{
|
||||
// play leave water sound
|
||||
sound (self, CHAN_BODY, "misc/outwater.wav", 1, ATTN_NORM);
|
||||
self.flags = self.flags - FL_INWATER;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.watertype == CONTENT_LAVA)
|
||||
{ // do damage
|
||||
if (self.dmgtime < time)
|
||||
{
|
||||
if (self.radsuit_finished > time)
|
||||
self.dmgtime = time + 1;
|
||||
else
|
||||
self.dmgtime = time + 0.2;
|
||||
|
||||
Damage (self, world, world, 10*self.waterlevel);
|
||||
}
|
||||
}
|
||||
else if (self.watertype == CONTENT_SLIME)
|
||||
{ // do damage
|
||||
if (self.dmgtime < time && self.radsuit_finished < time)
|
||||
{
|
||||
self.dmgtime = time + 1;
|
||||
|
||||
Damage (self, world, world, 4*self.waterlevel);
|
||||
}
|
||||
}
|
||||
|
||||
if ( !(self.flags & FL_INWATER) )
|
||||
{
|
||||
|
||||
// player enter water sound
|
||||
|
||||
if (self.watertype == CONTENT_LAVA)
|
||||
sound (self, CHAN_BODY, "player/inlava.wav", 1, ATTN_NORM);
|
||||
if (self.watertype == CONTENT_WATER)
|
||||
sound (self, CHAN_BODY, "player/inh2o.wav", 1, ATTN_NORM);
|
||||
if (self.watertype == CONTENT_SLIME)
|
||||
sound (self, CHAN_BODY, "player/slimbrn2.wav", 1, ATTN_NORM);
|
||||
|
||||
self.flags = self.flags + FL_INWATER;
|
||||
self.dmgtime = 0;
|
||||
}
|
||||
|
||||
if (! (self.flags & FL_WATERJUMP) )
|
||||
self.velocity = self.velocity - 0.8*self.waterlevel*frametime*self.velocity;
|
||||
};
|
||||
|
||||
/*
|
||||
================
|
||||
PlayerPreThink
|
||||
|
||||
Called every frame before physics are run
|
||||
================
|
||||
*/
|
||||
.float ladder_sound;
|
||||
.float ladder_time;
|
||||
|
||||
|
||||
void() PlayerPreThink =
|
||||
{
|
||||
if (intermission_running)
|
||||
{
|
||||
IntermissionThink();
|
||||
return;
|
||||
}
|
||||
if (self.deadflag)
|
||||
{
|
||||
PlayerDeathThink();
|
||||
return;
|
||||
}
|
||||
WaypointPreFrame();
|
||||
|
||||
CheckRules ();
|
||||
WaterMove ();
|
||||
|
||||
if (self.flags2 & FL2_ONLADDER)
|
||||
{
|
||||
self.flags2 = self.flags2 - FL2_ONLADDER;
|
||||
// climb
|
||||
if (self.button2)
|
||||
{
|
||||
// don't pogo stick if we drop off
|
||||
self.flags = self.flags - self.flags & FL_JUMPRELEASED;
|
||||
|
||||
self.velocity = '0 0 160';
|
||||
if (time > self.ladder_time)
|
||||
{
|
||||
self.ladder_time = time + 0.5;
|
||||
|
||||
self.ladder_sound = self.ladder_sound + 1;
|
||||
if (self.ladder_sound > 4)
|
||||
self.ladder_sound = 0;
|
||||
|
||||
if (self.ladder_sound == 0)
|
||||
sound(self, CHAN_BODY, "player/ladder1.wav", 1, ATTN_IDLE);
|
||||
if (self.ladder_sound == 1)
|
||||
sound(self, CHAN_BODY, "player/ladder2.wav", 1, ATTN_IDLE);
|
||||
if (self.ladder_sound == 2)
|
||||
sound(self, CHAN_BODY, "player/ladder3.wav", 1, ATTN_IDLE);
|
||||
if (self.ladder_sound == 3)
|
||||
sound(self, CHAN_BODY, "player/ladder4.wav", 1, ATTN_IDLE);
|
||||
if (self.ladder_sound == 4)
|
||||
sound(self, CHAN_BODY, "player/ladder5.wav", 1, ATTN_IDLE);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.flags = self.flags | FL_JUMPRELEASED;
|
||||
// restrict horizontal movement
|
||||
self.velocity = 0.9 * self.velocity;
|
||||
self.velocity_z = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.gravity = 1;
|
||||
if (self.button2)
|
||||
PlayerJump ();
|
||||
else
|
||||
self.flags = self.flags | FL_JUMPRELEASED;
|
||||
}
|
||||
|
||||
// teleporters can force a non-moving pause time
|
||||
if (time < self.pausetime)
|
||||
self.velocity = '0 0 0';
|
||||
|
||||
// check weapon ammo
|
||||
if (time > self.attack_finished && !W_CheckNoAmmo(self))
|
||||
{
|
||||
self.weapon = W_BestWeapon(self);
|
||||
W_UpdateWeapon(self);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
================
|
||||
CheckPowerups
|
||||
|
||||
Check for turning off powerups
|
||||
================
|
||||
*/
|
||||
void() CheckPowerups =
|
||||
{
|
||||
// megahelth
|
||||
if (self.items & IT_SUPERHEALTH)
|
||||
{
|
||||
if (self.health <= self.max_health)
|
||||
{
|
||||
self.items = self.items - IT_SUPERHEALTH;
|
||||
}
|
||||
else if (time > self.health_rot_time)
|
||||
{
|
||||
self.health = self.health - 1;
|
||||
self.health_rot_time = time + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// invisibility
|
||||
if (self.invisible_finished)
|
||||
{
|
||||
// sound and screen flash when items starts to run out
|
||||
if (self.invisible_sound < time)
|
||||
{
|
||||
sound (self, CHAN_AUTO, "items/inv3.wav", 0.5, ATTN_IDLE);
|
||||
self.invisible_sound = time + ((random() * 3) + 1);
|
||||
}
|
||||
|
||||
|
||||
if (self.invisible_finished < time + 3)
|
||||
{
|
||||
if (self.invisible_time == 1)
|
||||
{
|
||||
sprint (self, "Ring of Shadows magic is fading\n");
|
||||
stuffcmd (self, "bf\n");
|
||||
sound (self, CHAN_AUTO, "items/inv2.wav", 1, ATTN_NORM);
|
||||
self.invisible_time = time + 1;
|
||||
}
|
||||
|
||||
if (self.invisible_time < time)
|
||||
{
|
||||
self.invisible_time = time + 1;
|
||||
stuffcmd (self, "bf\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (self.invisible_finished < time)
|
||||
{ // just stopped
|
||||
self.items = self.items - IT_INVISIBILITY;
|
||||
self.invisible_finished = 0;
|
||||
self.invisible_time = 0;
|
||||
}
|
||||
|
||||
// use the eyes
|
||||
self.frame = 0;
|
||||
self.modelindex = modelindex_eyes;
|
||||
}
|
||||
else
|
||||
self.modelindex = modelindex_player; // don't use eyes
|
||||
|
||||
// invincibility
|
||||
if (self.invincible_finished)
|
||||
{
|
||||
// sound and screen flash when items starts to run out
|
||||
if (self.invincible_finished < time + 3)
|
||||
{
|
||||
if (self.invincible_time == 1)
|
||||
{
|
||||
sprint (self, "Protection is almost burned out\n");
|
||||
stuffcmd (self, "bf\n");
|
||||
sound (self, CHAN_AUTO, "items/protect2.wav", 1, ATTN_NORM);
|
||||
self.invincible_time = time + 1;
|
||||
}
|
||||
|
||||
if (self.invincible_time < time)
|
||||
{
|
||||
self.invincible_time = time + 1;
|
||||
stuffcmd (self, "bf\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (self.invincible_finished < time)
|
||||
{ // just stopped
|
||||
self.items = self.items - IT_INVULNERABILITY;
|
||||
self.invincible_time = 0;
|
||||
self.invincible_finished = 0;
|
||||
}
|
||||
if (self.invincible_finished > time)
|
||||
self.effects = self.effects | EF_DIMLIGHT;
|
||||
else
|
||||
self.effects = self.effects - (self.effects & EF_DIMLIGHT);
|
||||
}
|
||||
|
||||
// super damage
|
||||
if (self.super_damage_finished)
|
||||
{
|
||||
|
||||
// sound and screen flash when items starts to run out
|
||||
|
||||
if (self.super_damage_finished < time + 3)
|
||||
{
|
||||
if (self.super_time == 1)
|
||||
{
|
||||
sprint (self, "Quad Damage is wearing off\n");
|
||||
stuffcmd (self, "bf\n");
|
||||
sound (self, CHAN_AUTO, "items/damage2.wav", 1, ATTN_NORM);
|
||||
self.super_time = time + 1;
|
||||
}
|
||||
|
||||
if (self.super_time < time)
|
||||
{
|
||||
self.super_time = time + 1;
|
||||
stuffcmd (self, "bf\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (self.super_damage_finished < time)
|
||||
{ // just stopped
|
||||
self.items = self.items - IT_QUAD;
|
||||
self.super_damage_finished = 0;
|
||||
self.super_time = 0;
|
||||
}
|
||||
if (self.super_damage_finished > time)
|
||||
self.effects = self.effects | EF_DIMLIGHT;
|
||||
else
|
||||
self.effects = self.effects - (self.effects & EF_DIMLIGHT);
|
||||
}
|
||||
|
||||
// suit
|
||||
if (self.radsuit_finished)
|
||||
{
|
||||
self.air_finished = time + 12; // don't drown
|
||||
|
||||
// sound and screen flash when items starts to run out
|
||||
if (self.radsuit_finished < time + 3)
|
||||
{
|
||||
if (self.rad_time == 1)
|
||||
{
|
||||
sprint (self, "Air supply in Biosuit expiring\n");
|
||||
stuffcmd (self, "bf\n");
|
||||
sound (self, CHAN_AUTO, "items/suit2.wav", 1, ATTN_NORM);
|
||||
self.rad_time = time + 1;
|
||||
}
|
||||
|
||||
if (self.rad_time < time)
|
||||
{
|
||||
self.rad_time = time + 1;
|
||||
stuffcmd (self, "bf\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (self.radsuit_finished < time)
|
||||
{ // just stopped
|
||||
self.items = self.items - IT_SUIT;
|
||||
self.rad_time = 0;
|
||||
self.radsuit_finished = 0;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
PlayerPostThink
|
||||
|
||||
Called every frame after physics are run
|
||||
================
|
||||
*/
|
||||
|
||||
void() PlayerPostThink =
|
||||
{
|
||||
if (intermission_running || self.deadflag)
|
||||
return;
|
||||
|
||||
WaypointPostFrame();
|
||||
W_WeaponFrame ();
|
||||
|
||||
if ((self.jump_flag < -300) && (self.flags & FL_ONGROUND) && (self.health > 0))
|
||||
{
|
||||
if (self.watertype == CONTENT_WATER)
|
||||
sound (self, CHAN_BODY, "player/h2ojump.wav", 1, ATTN_NORM);
|
||||
else if (self.jump_flag < -650)
|
||||
{
|
||||
Damage (self, world, world, 5);
|
||||
sound (self, CHAN_VOICE, "player/land2.wav", 1, ATTN_NORM);
|
||||
self.deathtype = "falling";
|
||||
}
|
||||
else
|
||||
sound (self, CHAN_VOICE, "player/land.wav", 1, ATTN_NORM);
|
||||
|
||||
self.jump_flag = 0;
|
||||
}
|
||||
|
||||
if (!(self.flags & FL_ONGROUND))
|
||||
self.jump_flag = self.velocity_z;
|
||||
|
||||
|
||||
CheckPowerups ();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
ClientConnect
|
||||
|
||||
called when a player connects to a server
|
||||
============
|
||||
*/
|
||||
void() ClientConnect =
|
||||
{
|
||||
bprint (self.netname);
|
||||
bprint (" entered the game\n");
|
||||
|
||||
// a client connecting during an intermission can cause problems
|
||||
if (intermission_running)
|
||||
ExitIntermission();
|
||||
};
|
||||
|
||||
/*
|
||||
===========
|
||||
ClientDisconnect
|
||||
|
||||
called when a player disconnects from a server
|
||||
============
|
||||
*/
|
||||
void() ClientDisconnect =
|
||||
{
|
||||
// if the level end trigger has been activated, just return
|
||||
// since they aren't *really* leaving
|
||||
if (gameover)
|
||||
return;
|
||||
|
||||
self.classname = string_null;
|
||||
self.health = 0;
|
||||
sound (self, CHAN_BODY, "player/tornoff2.wav", 1, ATTN_NONE);
|
||||
|
||||
// let everyone else know
|
||||
bprint (self.netname);
|
||||
bprint (" left the game with ");
|
||||
bprint (ftos(self.frags));
|
||||
if (self.frags == 1)
|
||||
bprint (" frag\n");
|
||||
else
|
||||
bprint (" frags");
|
||||
|
||||
// already gibbed?
|
||||
if (self.model == "progs/h_player.mdl")
|
||||
return;
|
||||
|
||||
self.effects = 0;
|
||||
self.modelindex = modelindex_player;
|
||||
self.frame = 60; // $deatha11
|
||||
self.solid = SOLID_NOT;
|
||||
self.movetype = MOVETYPE_TOSS;
|
||||
self.deadflag = DEAD_DEAD;
|
||||
self.think = SUB_Null;
|
||||
self.nextthink = -1;
|
||||
};
|
||||
|
||||
215
mod_slipgate/source/server/damage.qc
Normal file
215
mod_slipgate/source/server/damage.qc
Normal file
@@ -0,0 +1,215 @@
|
||||
/*==========
|
||||
CanDamage
|
||||
|
||||
used for explosions and melee attacks
|
||||
==========*/
|
||||
float(entity targ, entity inflictor) CanDamage =
|
||||
{
|
||||
// bmodels need special checking because their origin is 0,0,0
|
||||
if (targ.movetype == MOVETYPE_PUSH)
|
||||
{
|
||||
traceline(inflictor.origin, realorigin(targ), TRUE, self);
|
||||
if (trace_fraction == 1)
|
||||
return TRUE;
|
||||
if (trace_ent == targ)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
traceline(inflictor.origin, targ.origin, TRUE, self);
|
||||
if (trace_fraction == 1)
|
||||
return TRUE;
|
||||
traceline(inflictor.origin, targ.origin + '15 15 0', TRUE, self);
|
||||
if (trace_fraction == 1)
|
||||
return TRUE;
|
||||
traceline(inflictor.origin, targ.origin + '-15 -15 0', TRUE, self);
|
||||
if (trace_fraction == 1)
|
||||
return TRUE;
|
||||
traceline(inflictor.origin, targ.origin + '-15 15 0', TRUE, self);
|
||||
if (trace_fraction == 1)
|
||||
return TRUE;
|
||||
traceline(inflictor.origin, targ.origin + '15 -15 0', TRUE, self);
|
||||
if (trace_fraction == 1)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
/*==========
|
||||
Killed
|
||||
==========*/
|
||||
void(entity targ, entity inflictor, entity attacker) Killed =
|
||||
{
|
||||
entity oself = self;
|
||||
self = targ;
|
||||
|
||||
// doors, triggers, etc
|
||||
if (self.movetype == MOVETYPE_PUSH || self.movetype == MOVETYPE_NONE)
|
||||
{
|
||||
self.th_die(inflictor, attacker);
|
||||
self = oself;
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.flags & FL_CLIENT)
|
||||
{
|
||||
// don't let sbar look bad
|
||||
if (self.health < -99)
|
||||
self.health = -99;
|
||||
|
||||
// display obituary text
|
||||
Obituary(self, attacker, inflictor);
|
||||
}
|
||||
|
||||
if (self.flags & FL_MONSTER)
|
||||
monster_death_use();
|
||||
|
||||
self.takedamage = DAMAGE_NO;
|
||||
self.touch = SUB_Null;
|
||||
|
||||
self.th_die (inflictor, attacker);
|
||||
|
||||
self = oself;
|
||||
};
|
||||
|
||||
/*==========
|
||||
Damage
|
||||
==========*/
|
||||
void(entity targ, entity inflictor, entity attacker, float damage) Damage =
|
||||
{
|
||||
if (!targ.takedamage)
|
||||
return;
|
||||
|
||||
// check for quad damage
|
||||
if (attacker.items & IT_QUAD)
|
||||
damage = damage * 4;
|
||||
|
||||
// save damage based upon armor
|
||||
float save, take;
|
||||
save = ceil(targ.armortype * damage);
|
||||
// lost all armor
|
||||
if (save >= targ.armorvalue)
|
||||
{
|
||||
save = targ.armorvalue;
|
||||
targ.armortype = 0;
|
||||
targ.items = targ.items - (targ.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3));
|
||||
}
|
||||
targ.armorvalue = targ.armorvalue - save;
|
||||
take = ceil(damage - save);
|
||||
|
||||
if (targ.flags & FL_CLIENT)
|
||||
{
|
||||
// add to the damage total for clients, which will be sent as a single
|
||||
// message at the end of the frame
|
||||
targ.dmg_take = targ.dmg_take + take;
|
||||
targ.dmg_save = targ.dmg_save + save;
|
||||
targ.dmg_inflictor = inflictor;
|
||||
}
|
||||
|
||||
// push players around
|
||||
if ( (inflictor != world) && (targ.movetype == MOVETYPE_WALK) )
|
||||
{
|
||||
vector dir = targ.origin - realorigin(inflictor);
|
||||
dir = normalize(dir);
|
||||
targ.velocity = targ.velocity + dir*damage*8;
|
||||
}
|
||||
|
||||
// check for godmode or pent
|
||||
if (targ.flags & FL_GODMODE)
|
||||
return;
|
||||
if (targ.items & IT_INVULNERABILITY)
|
||||
{
|
||||
if (targ.invincible_sound < time)
|
||||
{
|
||||
sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
|
||||
targ.invincible_sound = time + 2;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// team play damage avoidance
|
||||
if ((teamplay == 1) && (targ.team > 0) && (targ.team == attacker.team))
|
||||
return;
|
||||
|
||||
// do the damage
|
||||
targ.health = targ.health - take;
|
||||
if (targ.health <= 0)
|
||||
{
|
||||
Killed (targ, inflictor, attacker);
|
||||
return;
|
||||
}
|
||||
|
||||
// react to the damage
|
||||
entity oself = self;
|
||||
self = targ;
|
||||
|
||||
// monsters get mad, unless of the same class (except for grunts)
|
||||
if ( (self.flags & FL_MONSTER) && (attacker.flags & FL_CLIENT | FL_MONSTER) )
|
||||
{
|
||||
if (self != attacker && attacker != self.enemy)
|
||||
{
|
||||
if ( (self.classname != attacker.classname) || (self.classname == "monster_army" ) )
|
||||
{
|
||||
if (self.enemy.classname == "player")
|
||||
self.oldenemy = self.enemy;
|
||||
self.enemy = attacker;
|
||||
FoundTarget();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (self.th_pain)
|
||||
{
|
||||
self.th_pain (attacker, take);
|
||||
// nightmare mode monsters don't go into pain frames often
|
||||
if (skill == 3 && self.flags & FL_MONSTER)
|
||||
self.pain_finished = time + 5;
|
||||
}
|
||||
|
||||
self = oself;
|
||||
};
|
||||
|
||||
/*==========
|
||||
RadiusDamage
|
||||
==========*/
|
||||
void(entity inflictor, entity attacker, float damage, entity ignore) RadiusDamage =
|
||||
{
|
||||
float attacker_damaged = FALSE;
|
||||
float attacker_points = 0;
|
||||
entity head = findradius(inflictor.origin, damage + 40);
|
||||
while (head)
|
||||
{
|
||||
if (head != ignore)
|
||||
{
|
||||
if (head.takedamage)
|
||||
{
|
||||
vector org = realorigin(head);
|
||||
float points = 0.5*vlen (inflictor.origin - org);
|
||||
if (points < 0)
|
||||
points = 0;
|
||||
points = damage - points;
|
||||
if (points > 0)
|
||||
{
|
||||
if (CanDamage (head, inflictor))
|
||||
{
|
||||
if (head == attacker)
|
||||
{
|
||||
attacker_damaged = TRUE;
|
||||
attacker_points = points * 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (head.classname == "monster_shambler")
|
||||
Damage (head, inflictor, attacker, points * 0.5);
|
||||
else
|
||||
Damage (head, inflictor, attacker, points);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
head = head.chain;
|
||||
}
|
||||
|
||||
if (attacker_damaged)
|
||||
Damage (attacker, inflictor, attacker, attacker_points);
|
||||
};
|
||||
470
mod_slipgate/source/server/defs.qc
Normal file
470
mod_slipgate/source/server/defs.qc
Normal file
@@ -0,0 +1,470 @@
|
||||
/*========================================
|
||||
defs.qc
|
||||
========================================*/
|
||||
|
||||
/*==========
|
||||
System Globals
|
||||
==========*/
|
||||
|
||||
entity self, other, world;
|
||||
float time, frametime, force_retouch;
|
||||
string mapname;
|
||||
float deathmatch, coop, teamplay, serverflags;
|
||||
float total_secrets, total_monsters, found_secrets, killed_monsters;
|
||||
float parm1, parm2, parm3, parm4, parm5, parm6, parm7, parm8,
|
||||
parm9, parm10, parm11, parm12, parm13, parm14, parm15, parm16;
|
||||
vector v_forward, v_up, v_right;
|
||||
float trace_allsolid, trace_startsolid, trace_fraction;
|
||||
vector trace_endpos, trace_plane_normal;
|
||||
float trace_plane_dist;
|
||||
entity trace_ent;
|
||||
float trace_inopen, trace_inwater;
|
||||
entity msg_entity;
|
||||
void() main, StartFrame, PlayerPreThink, PlayerPostThink, ClientKill, ClientConnect,
|
||||
PutClientInServer, ClientDisconnect, SetNewParms, SetChangeParms;
|
||||
void end_sys_globals;
|
||||
|
||||
/*==========
|
||||
System Fields
|
||||
==========*/
|
||||
|
||||
.float modelindex;
|
||||
.vector absmin, absmax;
|
||||
.float ltime;
|
||||
.float movetype;
|
||||
.float solid;
|
||||
.vector origin;
|
||||
.vector oldorigin;
|
||||
.vector velocity;
|
||||
.vector angles;
|
||||
.vector avelocity;
|
||||
.vector punchangle;
|
||||
.string classname;
|
||||
.string model;
|
||||
.float frame;
|
||||
.float skin;
|
||||
.float effects;
|
||||
.vector mins, maxs;
|
||||
.vector size;
|
||||
.void() touch;
|
||||
.void() use;
|
||||
.void() think;
|
||||
.void() blocked;
|
||||
.float nextthink;
|
||||
.entity groundentity;
|
||||
.float health;
|
||||
.float frags;
|
||||
.float weapon;
|
||||
.string weaponmodel;
|
||||
.float weaponframe;
|
||||
.float currentammo;
|
||||
.float ammo_shells, ammo_nails, ammo_rockets, ammo_cells;
|
||||
.float items;
|
||||
.float takedamage;
|
||||
.entity chain;
|
||||
.float deadflag;
|
||||
.vector view_ofs;
|
||||
.float button0;
|
||||
.float button1;
|
||||
.float button2;
|
||||
.float impulse;
|
||||
.float fixangle;
|
||||
.vector v_angle;
|
||||
.float idealpitch;
|
||||
.string netname;
|
||||
.entity enemy;
|
||||
.float flags;
|
||||
.float colormap;
|
||||
.float team;
|
||||
.float max_health;
|
||||
.float teleport_time;
|
||||
.float armortype;
|
||||
.float armorvalue;
|
||||
.float waterlevel;
|
||||
.float watertype;
|
||||
.float ideal_yaw;
|
||||
.float yaw_speed;
|
||||
.entity aiment;
|
||||
.entity goalentity;
|
||||
.float spawnflags;
|
||||
.string target;
|
||||
.string targetname;
|
||||
.float dmg_take;
|
||||
.float dmg_save;
|
||||
.entity dmg_inflictor;
|
||||
.entity owner;
|
||||
.vector movedir;
|
||||
.string message;
|
||||
.float sounds;
|
||||
.string noise, noise1, noise2, noise3;
|
||||
void end_sys_fields;
|
||||
|
||||
/*==========
|
||||
Builtins
|
||||
==========*/
|
||||
|
||||
__used void(vector ang) makevectors = #1;
|
||||
__used void(entity e, vector o) setorigin = #2;
|
||||
__used void(entity e, string m) setmodel = #3;
|
||||
__used void(entity e, vector min, vector max) setsize = #4;
|
||||
__used void() break = #6;
|
||||
__used float() random = #7;
|
||||
__used void(entity e, float chan, string samp, float vol, float atten) sound = #8;
|
||||
__used vector(vector v) normalize = #9;
|
||||
__used void(string e) error = #10;
|
||||
__used void(string e) objerror = #11;
|
||||
__used float(vector v) vlen = #12;
|
||||
__used float(vector v) vectoyaw = #13;
|
||||
__used entity() spawn = #14;
|
||||
__used void(entity e) remove = #15;
|
||||
__used void(vector v1, vector v2, float nomonsters, entity forent) traceline = #16;
|
||||
__used entity() checkclient = #17;
|
||||
__used entity(entity start, .string fld, string match) find = #18;
|
||||
__used string(string s) precache_sound = #19;
|
||||
__used string(string s) precache_model = #20;
|
||||
__used void(entity client, string s) stuffcmd = #21;
|
||||
__used entity(vector org, float rad) findradius = #22;
|
||||
__used void(string s) bprint = #23;
|
||||
__used void(entity client, string s, optional string s2) sprint = #24;
|
||||
__used void(string s) dprint = #25;
|
||||
__used string(float f) ftos = #26;
|
||||
__used string(vector v) vtos = #27;
|
||||
__used void() coredump = #28;
|
||||
__used void() traceon = #29;
|
||||
__used void() traceoff = #30;
|
||||
__used void(entity e) eprint = #31;
|
||||
__used float(float yaw, float dist) walkmove = #32;
|
||||
__used float() droptofloor= #34;
|
||||
__used void(float style, string value) lightstyle = #35;
|
||||
__used float(float v) rint = #36;
|
||||
__used float(float v) floor = #37;
|
||||
__used float(float v) ceil = #38;
|
||||
__used float(entity e) checkbottom = #40;
|
||||
__used float(vector v) pointcontents = #41;
|
||||
__used float(float f) fabs = #43;
|
||||
__used vector(entity e, float speed) aim = #44;
|
||||
__used float(string s) cvar = #45;
|
||||
__used void(string s) localcmd = #46;
|
||||
__used entity(entity e) nextent = #47;
|
||||
__used void particle(vector o, vector d, float color, float count) = #48;
|
||||
__used void() changeyaw = #49;
|
||||
__used vector(vector v) vectoangles = #51;
|
||||
__used void(float to, float f) WriteByte = #52;
|
||||
__used void(float to, float f) WriteChar = #53;
|
||||
__used void(float to, float f) WriteShort = #54;
|
||||
__used void(float to, float f) WriteLong = #55;
|
||||
__used void(float to, float f) WriteCoord = #56;
|
||||
__used void(float to, float f) WriteAngle = #57;
|
||||
__used void(float to, string s) WriteString = #58;
|
||||
__used void(float to, entity s) WriteEntity = #59;
|
||||
__used void(float step) movetogoal = #67;
|
||||
__used string(string s) precache_file = #68;
|
||||
__used void(entity e) makestatic = #69;
|
||||
__used void(string s) changelevel = #70;
|
||||
__used void(string var, string val) cvar_set = #72;
|
||||
__used void(entity client, string s1, optional string s2, optional string s3,
|
||||
optional string s4, optional string s5, optional string s6, optional string s7) centerprint = #73;
|
||||
__used void(vector pos, string samp, float vol, float atten) ambientsound = #74;
|
||||
__used string(string s) precache_model2 = #75;
|
||||
__used string(string s) precache_sound2 = #76;
|
||||
__used string(string s) precache_file2 = #77;
|
||||
__used void(entity e) setspawnparms = #78;
|
||||
|
||||
/*==========
|
||||
Constants
|
||||
==========*/
|
||||
|
||||
// booleans
|
||||
const float FALSE = 0;
|
||||
const float TRUE = 1;
|
||||
|
||||
// flags
|
||||
float FL_FLY = 1;
|
||||
float FL_SWIM = 2;
|
||||
// 4 is unused
|
||||
float FL_CLIENT = 8;
|
||||
float FL_INWATER = 16;
|
||||
float FL_MONSTER = 32;
|
||||
float FL_GODMODE = 64;
|
||||
float FL_NOTARGET = 128;
|
||||
float FL_ITEM = 256;
|
||||
float FL_ONGROUND = 512;
|
||||
float FL_PARTIALGROUND = 1024;
|
||||
float FL_WATERJUMP = 2048;
|
||||
float FL_JUMPRELEASED = 4096;
|
||||
|
||||
// movetype
|
||||
float MOVETYPE_NONE = 0;
|
||||
float MOVETYPE_WALK = 3;
|
||||
float MOVETYPE_STEP = 4;
|
||||
float MOVETYPE_FLY = 5;
|
||||
float MOVETYPE_TOSS = 6;
|
||||
float MOVETYPE_PUSH = 7;
|
||||
float MOVETYPE_NOCLIP = 8;
|
||||
float MOVETYPE_FLYMISSILE = 9;
|
||||
float MOVETYPE_BOUNCE = 10;
|
||||
|
||||
// solid
|
||||
float SOLID_NOT = 0;
|
||||
float SOLID_TRIGGER = 1;
|
||||
float SOLID_BBOX = 2;
|
||||
float SOLID_SLIDEBOX = 3;
|
||||
float SOLID_BSP = 4;
|
||||
|
||||
// range
|
||||
float RANGE_MELEE = 0;
|
||||
float RANGE_NEAR = 1;
|
||||
float RANGE_MID = 2;
|
||||
float RANGE_FAR = 3;
|
||||
|
||||
// deadflag
|
||||
float DEAD_NO = 0;
|
||||
float DEAD_DYING = 1;
|
||||
float DEAD_DEAD = 2;
|
||||
float DEAD_RESPAWNABLE = 4;
|
||||
|
||||
// takedamage
|
||||
float DAMAGE_NO = 0;
|
||||
float DAMAGE_YES = 1;
|
||||
float DAMAGE_AIM = 2;
|
||||
|
||||
// items
|
||||
float IT_SHOTGUN = 1;
|
||||
float IT_SUPER_SHOTGUN = 2;
|
||||
float IT_NAILGUN = 4;
|
||||
float IT_SUPER_NAILGUN = 8;
|
||||
float IT_GRENADE_LAUNCHER = 16;
|
||||
float IT_ROCKET_LAUNCHER = 32;
|
||||
float IT_LIGHTNING = 64;
|
||||
float IT_EXTRA_WEAPON = 128;
|
||||
float IT_SHELLS = 256;
|
||||
float IT_NAILS = 512;
|
||||
float IT_ROCKETS = 1024;
|
||||
float IT_CELLS = 2048;
|
||||
float IT_AXE = 4096;
|
||||
float IT_ARMOR1 = 8192;
|
||||
float IT_ARMOR2 = 16384;
|
||||
float IT_ARMOR3 = 32768;
|
||||
float IT_SUPERHEALTH = 65536;
|
||||
float IT_KEY1 = 131072;
|
||||
float IT_KEY2 = 262144;
|
||||
float IT_INVISIBILITY = 524288;
|
||||
float IT_INVULNERABILITY = 1048576;
|
||||
float IT_SUIT = 2097152;
|
||||
float IT_QUAD = 4194304;
|
||||
|
||||
// content
|
||||
float CONTENT_EMPTY = -1;
|
||||
float CONTENT_SOLID = -2;
|
||||
float CONTENT_WATER = -3;
|
||||
float CONTENT_SLIME = -4;
|
||||
float CONTENT_LAVA = -5;
|
||||
float CONTENT_SKY = -6;
|
||||
|
||||
// state
|
||||
float STATE_TOP = 0;
|
||||
float STATE_BOTTOM = 1;
|
||||
float STATE_UP = 2;
|
||||
float STATE_DOWN = 3;
|
||||
|
||||
// hull sizes
|
||||
vector VEC_ORIGIN = '0 0 0';
|
||||
vector VEC_HULL_MIN = '-16 -16 -24';
|
||||
vector VEC_HULL_MAX = '16 16 32';
|
||||
vector VEC_HULL2_MIN = '-32 -32 -24';
|
||||
vector VEC_HULL2_MAX = '32 32 64';
|
||||
|
||||
// protocol bytes
|
||||
float SVC_BAD = 0;
|
||||
float SVC_NOP = 1;
|
||||
float SVC_DISCONNECT = 2;
|
||||
float SVC_UPDATESTAT = 3;
|
||||
float SVC_VERSION = 4;
|
||||
float SVC_SETVIEW = 5;
|
||||
float SVC_SOUND = 6;
|
||||
float SVC_TIME = 7;
|
||||
float SVC_PRINT = 8;
|
||||
float SVC_STUFFTEXT = 9;
|
||||
float SVC_SETANGLE = 10;
|
||||
float SVC_SERVERINFO = 11;
|
||||
float SVC_LIGHTSTYLE = 12;
|
||||
float SVC_UPDATENAME = 13;
|
||||
float SVC_UPDATEFRAGS = 14;
|
||||
float SVC_CLIENTDATA = 15;
|
||||
float SVC_STOPSOUND = 16;
|
||||
float SVC_UPDATECOLORS = 17;
|
||||
float SVC_PARTICLE = 18;
|
||||
float SVC_DAMAGE = 19;
|
||||
float SVC_SPAWNSTATIC = 20;
|
||||
float SVC_SPAWNBINARY = 21;
|
||||
float SVC_SPAWNBASELINE = 22;
|
||||
float SVC_TEMPENTITY = 23;
|
||||
float SVC_SETPAUSE = 24;
|
||||
float SVC_SIGNONNUM = 25;
|
||||
float SVC_CENTERPRINT = 26;
|
||||
float SVC_KILLEDMONSTER = 27;
|
||||
float SVC_FOUNDSECRET = 28;
|
||||
float SVC_SPAWNSTATICSOUND= 29;
|
||||
float SVC_INTERMISSION = 30;
|
||||
float SVC_FINALE = 31;
|
||||
float SVC_CDTRACK = 32;
|
||||
float SVC_SELLSCREEN = 33;
|
||||
float SVC_CUTSCENE = 34;
|
||||
|
||||
// stats
|
||||
float STAT_HEALTH = 0;
|
||||
float STAT_FRAGS = 1;
|
||||
float STAT_WEAPON = 2;
|
||||
float STAT_AMMO = 3;
|
||||
float STAT_ARMOR = 4;
|
||||
float STAT_WEAPONFRAME = 5;
|
||||
float STAT_SHELLS = 6;
|
||||
float STAT_NAILS = 7;
|
||||
float STAT_ROCKETS = 8;
|
||||
float STAT_CELLS = 9;
|
||||
float STAT_ACTIVEWEAPON = 10;
|
||||
float STAT_TOTALSECRETS = 11;
|
||||
float STAT_TOTALMONSTERS = 12;
|
||||
float STAT_SECRETS = 13;
|
||||
float STAT_MONSTERS = 14;
|
||||
|
||||
// temp ents
|
||||
float TE_SPIKE = 0;
|
||||
float TE_SUPERSPIKE = 1;
|
||||
float TE_GUNSHOT = 2;
|
||||
float TE_EXPLOSION = 3;
|
||||
float TE_TAREXPLOSION = 4;
|
||||
float TE_LIGHTNING1 = 5;
|
||||
float TE_LIGHTNING2 = 6;
|
||||
float TE_WIZSPIKE = 7;
|
||||
float TE_KNIGHTSPIKE = 8;
|
||||
float TE_LIGHTNING3 = 9;
|
||||
float TE_LAVASPLASH = 10;
|
||||
float TE_TELEPORT = 11;
|
||||
float TE_EXPLOSION2 = 12;
|
||||
float TE_BEAM = 13;
|
||||
|
||||
// sound channels
|
||||
float CHAN_AUTO = 0;
|
||||
float CHAN_WEAPON = 1;
|
||||
float CHAN_VOICE = 2;
|
||||
float CHAN_ITEM = 3;
|
||||
float CHAN_BODY = 4;
|
||||
|
||||
// sound attenuation
|
||||
float ATTN_NONE = 0;
|
||||
float ATTN_NORM = 1;
|
||||
float ATTN_IDLE = 2;
|
||||
float ATTN_STATIC = 3;
|
||||
|
||||
// update types
|
||||
float UPDATE_GENERAL = 0;
|
||||
float UPDATE_STATIC = 1;
|
||||
float UPDATE_BINARY = 2;
|
||||
float UPDATE_TEMP = 3;
|
||||
|
||||
// effects
|
||||
float EF_BRIGHTFIELD = 1;
|
||||
float EF_MUZZLEFLASH = 2;
|
||||
float EF_BRIGHTLIGHT = 4;
|
||||
float EF_DIMLIGHT = 8;
|
||||
|
||||
// messages
|
||||
float MSG_BROADCAST = 0;
|
||||
float MSG_ONE = 1;
|
||||
float MSG_ALL = 2;
|
||||
float MSG_INIT = 3;
|
||||
|
||||
// attack styles
|
||||
float AS_STRAIGHT = 1;
|
||||
float AS_SLIDING = 2;
|
||||
float AS_MELEE = 3;
|
||||
float AS_MISSILE = 4;
|
||||
float AS_SPAM = 5;
|
||||
|
||||
// traceline flags
|
||||
float MOVE_NORMAL = 0;
|
||||
float MOVE_NOMONSTERS = 1;
|
||||
float MOVE_MISSILE = 2;
|
||||
|
||||
// flags2
|
||||
float FL2_ONLADDER = 1;
|
||||
float FL2_PROJECTILE = 2;
|
||||
|
||||
/*==========
|
||||
Globals
|
||||
==========*/
|
||||
|
||||
string string_null;
|
||||
entity newmis;
|
||||
entity activator;
|
||||
float framecount;
|
||||
float skill;
|
||||
entity lastspawn;
|
||||
float developer;
|
||||
float sv_gravity;
|
||||
float gameover, intermission_running, intermission_exittime;
|
||||
string nextmap;
|
||||
|
||||
/*==========
|
||||
Fields
|
||||
==========*/
|
||||
|
||||
// not used by gamecode, but used by map compiling utilities, so included to stop console warnings
|
||||
__used .float light_lev;
|
||||
__used .string wad;
|
||||
|
||||
// pain and death
|
||||
.void(entity inflictor, entity attacker) th_die;
|
||||
.void(entity attacker, float damage) th_pain;
|
||||
|
||||
// monster AI
|
||||
.void() th_stand;
|
||||
.void() th_walk;
|
||||
.void() th_run;
|
||||
.void() th_missile;
|
||||
.void() th_melee;
|
||||
.void() th_spam;
|
||||
|
||||
.float alpha;
|
||||
.vector finaldest;
|
||||
.float gravity;
|
||||
.string killtarget;
|
||||
.string map;
|
||||
.float style;
|
||||
.float style2;
|
||||
.float switchshadstyle;
|
||||
.void() think1;
|
||||
.float worldtype;
|
||||
.entity trigger_field;
|
||||
.float cnt, colour, count, delay, distance, dmg, height, lip, pausetime, speed, state, volume, wait;
|
||||
.float t_length, t_width;
|
||||
.string mdl, mdl1, mdl2, mdl3, headmodel;
|
||||
.string noise4;
|
||||
.vector dest1, dest2;
|
||||
.vector pos1, pos2;
|
||||
.vector mangle, oldorigin;
|
||||
.float attack_finished, pain_finished;
|
||||
.float attack_state;
|
||||
.entity movetarget, oldenemy;
|
||||
.float lefty;
|
||||
.float search_time;
|
||||
.float show_hostile;
|
||||
.float air_finished, fly_sound, health_rot_time, hurt_time, jump_flag, swim_flag, walkframe;
|
||||
.string deathtype;
|
||||
.float flags2;
|
||||
|
||||
// powerups
|
||||
.float invincible_finished, invincible_time, invincible_sound;
|
||||
.float invisible_finished, invisible_time, invisible_sound;
|
||||
.float super_damage_finished, super_time, super_sound;
|
||||
.float radsuit_finished, rad_time;
|
||||
|
||||
/*==========
|
||||
Prototypes
|
||||
==========*/
|
||||
|
||||
void() monster_death_use;
|
||||
void() FoundTarget;
|
||||
void(vector org, entity who) spawn_tdeath;
|
||||
void(vector org) spawn_tfog;
|
||||
795
mod_slipgate/source/server/doors.qc
Normal file
795
mod_slipgate/source/server/doors.qc
Normal file
@@ -0,0 +1,795 @@
|
||||
|
||||
float DOOR_START_OPEN = 1;
|
||||
float DOOR_DONT_LINK = 4;
|
||||
float DOOR_GOLD_KEY = 8;
|
||||
float DOOR_SILVER_KEY = 16;
|
||||
float DOOR_TOGGLE = 32;
|
||||
|
||||
/*
|
||||
|
||||
Doors are similar to buttons, but can spawn a fat trigger field around them
|
||||
to open without a touch, and they link together to form simultanious
|
||||
double/quad doors.
|
||||
|
||||
Door.owner is the master door. If there is only one door, it points to itself.
|
||||
If multiple doors, all will point to a single one.
|
||||
|
||||
Door.enemy chains from the master door through all doors linked in the chain.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
THINK FUNCTIONS
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
void() door_go_down;
|
||||
void() door_go_up;
|
||||
|
||||
void() door_blocked =
|
||||
{
|
||||
Damage (other, self, self, self.dmg);
|
||||
|
||||
// if a door has a negative wait, it would never come back if blocked,
|
||||
// so let it just squash the object to death real fast
|
||||
if (self.wait >= 0)
|
||||
{
|
||||
if (self.state == STATE_DOWN)
|
||||
door_go_up ();
|
||||
else
|
||||
door_go_down ();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void() door_hit_top =
|
||||
{
|
||||
sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
|
||||
self.state = STATE_TOP;
|
||||
if (self.spawnflags & DOOR_TOGGLE)
|
||||
return; // don't come down automatically
|
||||
self.think = door_go_down;
|
||||
self.nextthink = self.ltime + self.wait;
|
||||
};
|
||||
|
||||
void() door_hit_bottom =
|
||||
{
|
||||
sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
|
||||
self.state = STATE_BOTTOM;
|
||||
};
|
||||
|
||||
void() door_go_down =
|
||||
{
|
||||
sound (self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
|
||||
if (self.max_health)
|
||||
{
|
||||
self.takedamage = DAMAGE_YES;
|
||||
self.health = self.max_health;
|
||||
}
|
||||
|
||||
self.state = STATE_DOWN;
|
||||
SUB_CalcMove (self.pos1, self.speed, door_hit_bottom);
|
||||
};
|
||||
|
||||
void() door_go_up =
|
||||
{
|
||||
if (self.state == STATE_UP)
|
||||
return; // allready going up
|
||||
|
||||
if (self.state == STATE_TOP)
|
||||
{ // reset top wait time
|
||||
self.nextthink = self.ltime + self.wait;
|
||||
return;
|
||||
}
|
||||
|
||||
sound (self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
|
||||
self.state = STATE_UP;
|
||||
SUB_CalcMove (self.pos2, self.speed, door_hit_top);
|
||||
|
||||
UseTargets();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
ACTIVATION FUNCTIONS
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
void() door_fire =
|
||||
{
|
||||
local entity oself;
|
||||
local entity starte;
|
||||
|
||||
if (self.owner != self)
|
||||
objerror ("door_fire: self.owner != self");
|
||||
|
||||
// play use key sound
|
||||
|
||||
if (self.items)
|
||||
sound (self, CHAN_ITEM, self.noise4, 1, ATTN_NORM);
|
||||
|
||||
self.message = string_null; // no more message
|
||||
oself = self;
|
||||
|
||||
if (self.spawnflags & DOOR_TOGGLE)
|
||||
{
|
||||
if (self.state == STATE_UP || self.state == STATE_TOP)
|
||||
{
|
||||
starte = self;
|
||||
do
|
||||
{
|
||||
door_go_down ();
|
||||
self = self.enemy;
|
||||
} while ( (self != starte) && (self != world) );
|
||||
self = oself;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// trigger all paired doors
|
||||
starte = self;
|
||||
do
|
||||
{
|
||||
door_go_up ();
|
||||
self = self.enemy;
|
||||
} while ( (self != starte) && (self != world) );
|
||||
self = oself;
|
||||
};
|
||||
|
||||
|
||||
void() door_use =
|
||||
{
|
||||
local entity oself;
|
||||
|
||||
self.message = ""; // door message are for touch only
|
||||
self.owner.message = "";
|
||||
self.enemy.message = "";
|
||||
oself = self;
|
||||
self = self.owner;
|
||||
door_fire ();
|
||||
self = oself;
|
||||
};
|
||||
|
||||
|
||||
void() door_trigger_touch =
|
||||
{
|
||||
if (other.health <= 0)
|
||||
return;
|
||||
|
||||
if (time < self.attack_finished)
|
||||
return;
|
||||
self.attack_finished = time + 1;
|
||||
|
||||
activator = other;
|
||||
|
||||
self = self.owner;
|
||||
door_use ();
|
||||
};
|
||||
|
||||
|
||||
void(entity inflictor, entity attacker) door_killed =
|
||||
{
|
||||
local entity oself;
|
||||
|
||||
oself = self;
|
||||
self = self.owner;
|
||||
self.health = self.max_health;
|
||||
self.takedamage = DAMAGE_NO; // wil be reset upon return
|
||||
door_use ();
|
||||
self = oself;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
door_touch
|
||||
|
||||
Prints messages and opens key doors
|
||||
================
|
||||
*/
|
||||
void() door_touch =
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
if (self.owner.attack_finished > time)
|
||||
return;
|
||||
|
||||
self.owner.attack_finished = time + 2;
|
||||
|
||||
if (self.owner.message != "")
|
||||
{
|
||||
centerprint (other, self.owner.message);
|
||||
sound (other, CHAN_VOICE, "misc/talk.wav", 1, ATTN_NORM);
|
||||
}
|
||||
|
||||
// key door stuff
|
||||
if (!self.items)
|
||||
return;
|
||||
|
||||
// FIXME: blink key on player's status bar
|
||||
if ( (self.items & other.items) != self.items )
|
||||
{
|
||||
if (self.owner.items == IT_KEY1)
|
||||
{
|
||||
if (world.worldtype == 2)
|
||||
{
|
||||
centerprint (other, "You need the silver keycard");
|
||||
sound (self, CHAN_ITEM, self.noise3, 1, ATTN_NORM);
|
||||
}
|
||||
else if (world.worldtype == 1)
|
||||
{
|
||||
centerprint (other, "You need the silver runekey");
|
||||
sound (self, CHAN_ITEM, self.noise3, 1, ATTN_NORM);
|
||||
}
|
||||
else if (world.worldtype == 0)
|
||||
{
|
||||
centerprint (other, "You need the silver key");
|
||||
sound (self, CHAN_ITEM, self.noise3, 1, ATTN_NORM);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (world.worldtype == 2)
|
||||
{
|
||||
centerprint (other, "You need the gold keycard");
|
||||
sound (self, CHAN_ITEM, self.noise3, 1, ATTN_NORM);
|
||||
}
|
||||
else if (world.worldtype == 1)
|
||||
{
|
||||
centerprint (other, "You need the gold runekey");
|
||||
sound (self, CHAN_ITEM, self.noise3, 1, ATTN_NORM);
|
||||
}
|
||||
else if (world.worldtype == 0)
|
||||
{
|
||||
centerprint (other, "You need the gold key");
|
||||
sound (self, CHAN_ITEM, self.noise3, 1, ATTN_NORM);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
other.items = other.items - self.items;
|
||||
self.touch = SUB_Null;
|
||||
if (self.enemy)
|
||||
self.enemy.touch = SUB_Null; // get paired door
|
||||
door_use ();
|
||||
};
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
SPAWNING FUNCTIONS
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
|
||||
entity(vector fmins, vector fmaxs) spawn_field =
|
||||
{
|
||||
local entity trigger;
|
||||
local vector t1, t2;
|
||||
|
||||
trigger = spawn();
|
||||
trigger.movetype = MOVETYPE_NONE;
|
||||
trigger.solid = SOLID_TRIGGER;
|
||||
trigger.owner = self;
|
||||
trigger.touch = door_trigger_touch;
|
||||
|
||||
t1 = fmins;
|
||||
t2 = fmaxs;
|
||||
setsize (trigger, t1 - '60 60 8', t2 + '60 60 8');
|
||||
return (trigger);
|
||||
};
|
||||
|
||||
|
||||
float (entity e1, entity e2) EntitiesTouching =
|
||||
{
|
||||
if (e1.mins_x > e2.maxs_x)
|
||||
return FALSE;
|
||||
if (e1.mins_y > e2.maxs_y)
|
||||
return FALSE;
|
||||
if (e1.mins_z > e2.maxs_z)
|
||||
return FALSE;
|
||||
if (e1.maxs_x < e2.mins_x)
|
||||
return FALSE;
|
||||
if (e1.maxs_y < e2.mins_y)
|
||||
return FALSE;
|
||||
if (e1.maxs_z < e2.mins_z)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
LinkDoors
|
||||
|
||||
|
||||
=============
|
||||
*/
|
||||
void() LinkDoors =
|
||||
{
|
||||
local entity t, starte;
|
||||
local vector cmins, cmaxs;
|
||||
|
||||
if (self.enemy)
|
||||
return; // already linked by another door
|
||||
if (self.spawnflags & 4)
|
||||
{
|
||||
self.owner = self.enemy = self;
|
||||
return; // don't want to link this door
|
||||
}
|
||||
|
||||
cmins = self.mins;
|
||||
cmaxs = self.maxs;
|
||||
|
||||
starte = self;
|
||||
t = self;
|
||||
|
||||
do
|
||||
{
|
||||
self.owner = starte; // master door
|
||||
|
||||
if (self.health)
|
||||
starte.health = self.health;
|
||||
if (self.targetname != "")
|
||||
starte.targetname = self.targetname;
|
||||
if (self.message != "")
|
||||
starte.message = self.message;
|
||||
|
||||
t = find (t, classname, self.classname);
|
||||
if (!t)
|
||||
{
|
||||
self.enemy = starte; // make the chain a loop
|
||||
|
||||
// shootable, fired, or key doors just needed the owner/enemy links,
|
||||
// they don't spawn a field
|
||||
|
||||
self = self.owner;
|
||||
|
||||
if (self.health)
|
||||
return;
|
||||
if (self.targetname != "")
|
||||
return;
|
||||
if (self.items)
|
||||
return;
|
||||
|
||||
self.owner.trigger_field = spawn_field(cmins, cmaxs);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (EntitiesTouching(self,t))
|
||||
{
|
||||
if (t.enemy)
|
||||
objerror ("cross connected doors");
|
||||
|
||||
self.enemy = t;
|
||||
self = t;
|
||||
|
||||
if (t.mins_x < cmins_x)
|
||||
cmins_x = t.mins_x;
|
||||
if (t.mins_y < cmins_y)
|
||||
cmins_y = t.mins_y;
|
||||
if (t.mins_z < cmins_z)
|
||||
cmins_z = t.mins_z;
|
||||
if (t.maxs_x > cmaxs_x)
|
||||
cmaxs_x = t.maxs_x;
|
||||
if (t.maxs_y > cmaxs_y)
|
||||
cmaxs_y = t.maxs_y;
|
||||
if (t.maxs_z > cmaxs_z)
|
||||
cmaxs_z = t.maxs_z;
|
||||
}
|
||||
} while (1 );
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*QUAKED func_door (0 .5 .8) ? START_OPEN x DOOR_DONT_LINK GOLD_KEY SILVER_KEY TOGGLE
|
||||
if two doors touch, they are assumed to be connected and operate as a unit.
|
||||
|
||||
TOGGLE causes the door to wait in both the start and end states for a trigger event.
|
||||
|
||||
START_OPEN causes the door to move to its destination when spawned, and operate in reverse. It is used to temporarily or permanently close off an area when triggered (not usefull for touch or takedamage doors).
|
||||
|
||||
Key doors are allways wait -1.
|
||||
|
||||
"message" is printed when the door is touched if it is a trigger door and it hasn't been fired yet
|
||||
"angle" determines the opening direction
|
||||
"targetname" if set, no touch field will be spawned and a remote button or trigger field activates the door.
|
||||
"health" if set, door must be shot open
|
||||
"speed" movement speed (100 default)
|
||||
"wait" wait before returning (3 default, -1 = never return)
|
||||
"lip" lip remaining at end of move (8 default)
|
||||
"dmg" damage to inflict when blocked (2 default)
|
||||
"sounds"
|
||||
0) no sound
|
||||
1) stone
|
||||
2) base
|
||||
3) stone chain
|
||||
4) screechy metal
|
||||
*/
|
||||
|
||||
void() func_door =
|
||||
|
||||
{
|
||||
|
||||
if (world.worldtype == 0)
|
||||
{
|
||||
precache_sound ("doors/medtry.wav");
|
||||
precache_sound ("doors/meduse.wav");
|
||||
self.noise3 = "doors/medtry.wav";
|
||||
self.noise4 = "doors/meduse.wav";
|
||||
}
|
||||
else if (world.worldtype == 1)
|
||||
{
|
||||
precache_sound ("doors/runetry.wav");
|
||||
precache_sound ("doors/runeuse.wav");
|
||||
self.noise3 = "doors/runetry.wav";
|
||||
self.noise4 = "doors/runeuse.wav";
|
||||
}
|
||||
else if (world.worldtype == 2)
|
||||
{
|
||||
precache_sound ("doors/basetry.wav");
|
||||
precache_sound ("doors/baseuse.wav");
|
||||
self.noise3 = "doors/basetry.wav";
|
||||
self.noise4 = "doors/baseuse.wav";
|
||||
}
|
||||
else
|
||||
{
|
||||
dprint ("no worldtype set!\n");
|
||||
}
|
||||
if (self.sounds == 0)
|
||||
{
|
||||
precache_sound ("misc/null.wav");
|
||||
precache_sound ("misc/null.wav");
|
||||
self.noise1 = "misc/null.wav";
|
||||
self.noise2 = "misc/null.wav";
|
||||
}
|
||||
if (self.sounds == 1)
|
||||
{
|
||||
precache_sound ("doors/drclos4.wav");
|
||||
precache_sound ("doors/doormv1.wav");
|
||||
self.noise1 = "doors/drclos4.wav";
|
||||
self.noise2 = "doors/doormv1.wav";
|
||||
}
|
||||
if (self.sounds == 2)
|
||||
{
|
||||
precache_sound ("doors/hydro1.wav");
|
||||
precache_sound ("doors/hydro2.wav");
|
||||
self.noise2 = "doors/hydro1.wav";
|
||||
self.noise1 = "doors/hydro2.wav";
|
||||
}
|
||||
if (self.sounds == 3)
|
||||
{
|
||||
precache_sound ("doors/stndr1.wav");
|
||||
precache_sound ("doors/stndr2.wav");
|
||||
self.noise2 = "doors/stndr1.wav";
|
||||
self.noise1 = "doors/stndr2.wav";
|
||||
}
|
||||
if (self.sounds == 4)
|
||||
{
|
||||
precache_sound ("doors/ddoor1.wav");
|
||||
precache_sound ("doors/ddoor2.wav");
|
||||
self.noise1 = "doors/ddoor2.wav";
|
||||
self.noise2 = "doors/ddoor1.wav";
|
||||
}
|
||||
|
||||
|
||||
SetMovedir ();
|
||||
|
||||
self.max_health = self.health;
|
||||
self.solid = SOLID_BSP;
|
||||
self.movetype = MOVETYPE_PUSH;
|
||||
setorigin (self, self.origin);
|
||||
setmodel (self, self.model);
|
||||
self.classname = "door";
|
||||
|
||||
self.blocked = door_blocked;
|
||||
self.use = door_use;
|
||||
|
||||
if (self.spawnflags & DOOR_SILVER_KEY)
|
||||
self.items = IT_KEY1;
|
||||
if (self.spawnflags & DOOR_GOLD_KEY)
|
||||
self.items = IT_KEY2;
|
||||
|
||||
if (!self.speed)
|
||||
self.speed = 100;
|
||||
if (!self.wait)
|
||||
self.wait = 3;
|
||||
if (!self.lip)
|
||||
self.lip = 8;
|
||||
if (!self.dmg)
|
||||
self.dmg = 2;
|
||||
|
||||
self.colour = 192;
|
||||
|
||||
self.pos1 = self.origin;
|
||||
self.pos2 = self.pos1 + self.movedir*(fabs(self.movedir*self.size) - self.lip);
|
||||
|
||||
// DOOR_START_OPEN is to allow an entity to be lighted in the closed position
|
||||
// but spawn in the open position
|
||||
if (self.spawnflags & DOOR_START_OPEN)
|
||||
{
|
||||
setorigin (self, self.pos2);
|
||||
self.pos2 = self.pos1;
|
||||
self.pos1 = self.origin;
|
||||
}
|
||||
|
||||
self.state = STATE_BOTTOM;
|
||||
|
||||
if (self.health)
|
||||
{
|
||||
self.takedamage = DAMAGE_YES;
|
||||
self.th_die = door_killed;
|
||||
}
|
||||
|
||||
if (self.items)
|
||||
self.wait = -1;
|
||||
|
||||
self.touch = door_touch;
|
||||
|
||||
// LinkDoors can't be done until all of the doors have been spawned, so
|
||||
// the sizes can be detected properly.
|
||||
self.think = LinkDoors;
|
||||
self.nextthink = self.ltime + 0.1;
|
||||
};
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
SECRET DOORS
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
void() fd_secret_move1;
|
||||
void() fd_secret_move2;
|
||||
void() fd_secret_move3;
|
||||
void() fd_secret_move4;
|
||||
void() fd_secret_move5;
|
||||
void() fd_secret_move6;
|
||||
void() fd_secret_done;
|
||||
|
||||
float SECRET_OPEN_ONCE = 1; // stays open
|
||||
float SECRET_1ST_LEFT = 2; // 1st move is left of arrow
|
||||
float SECRET_1ST_DOWN = 4; // 1st move is down from arrow
|
||||
float SECRET_NO_SHOOT = 8; // only opened by trigger
|
||||
float SECRET_YES_SHOOT = 16; // shootable even if targeted
|
||||
|
||||
|
||||
void () fd_secret_use =
|
||||
{
|
||||
local float temp;
|
||||
|
||||
self.health = 10000;
|
||||
|
||||
// exit if still moving around...
|
||||
if (self.origin != self.oldorigin)
|
||||
return;
|
||||
|
||||
self.message = string_null; // no more message
|
||||
|
||||
UseTargets(); // fire all targets / killtargets
|
||||
|
||||
if (!(self.spawnflags & SECRET_NO_SHOOT))
|
||||
{
|
||||
self.th_pain = SUB_PainNull;
|
||||
self.takedamage = DAMAGE_NO;
|
||||
}
|
||||
self.velocity = '0 0 0';
|
||||
|
||||
// Make a sound, wait a little...
|
||||
|
||||
sound(self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
|
||||
self.nextthink = self.ltime + 0.1;
|
||||
|
||||
temp = 1 - (self.spawnflags & SECRET_1ST_LEFT); // 1 or -1
|
||||
makevectors(self.mangle);
|
||||
|
||||
if (!self.t_width)
|
||||
{
|
||||
if (self.spawnflags & SECRET_1ST_DOWN)
|
||||
self. t_width = fabs(v_up * self.size);
|
||||
else
|
||||
self. t_width = fabs(v_right * self.size);
|
||||
}
|
||||
|
||||
if (!self.t_length)
|
||||
self. t_length = fabs(v_forward * self.size);
|
||||
|
||||
if (self.spawnflags & SECRET_1ST_DOWN)
|
||||
self.dest1 = self.origin - v_up * self.t_width;
|
||||
else
|
||||
self.dest1 = self.origin + v_right * (self.t_width * temp);
|
||||
|
||||
self.dest2 = self.dest1 + v_forward * self.t_length;
|
||||
SUB_CalcMove(self.dest1, self.speed, fd_secret_move1);
|
||||
sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
|
||||
};
|
||||
|
||||
|
||||
void(entity attacker, float damage) fd_secret_pain =
|
||||
{
|
||||
fd_secret_use();
|
||||
};
|
||||
|
||||
void(entity inflictor, entity attacker) fd_secret_die =
|
||||
{
|
||||
fd_secret_use();
|
||||
};
|
||||
|
||||
// Wait after first movement...
|
||||
void () fd_secret_move1 =
|
||||
{
|
||||
self.nextthink = self.ltime + 1.0;
|
||||
self.think = fd_secret_move2;
|
||||
sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
|
||||
};
|
||||
|
||||
// Start moving sideways w/sound...
|
||||
void () fd_secret_move2 =
|
||||
{
|
||||
sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
|
||||
SUB_CalcMove(self.dest2, self.speed, fd_secret_move3);
|
||||
};
|
||||
|
||||
// Wait here until time to go back...
|
||||
void () fd_secret_move3 =
|
||||
{
|
||||
sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
|
||||
if (!(self.spawnflags & SECRET_OPEN_ONCE))
|
||||
{
|
||||
self.nextthink = self.ltime + self.wait;
|
||||
self.think = fd_secret_move4;
|
||||
}
|
||||
};
|
||||
|
||||
// Move backward...
|
||||
void () fd_secret_move4 =
|
||||
{
|
||||
sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
|
||||
SUB_CalcMove(self.dest1, self.speed, fd_secret_move5);
|
||||
};
|
||||
|
||||
// Wait 1 second...
|
||||
void () fd_secret_move5 =
|
||||
{
|
||||
self.nextthink = self.ltime + 1.0;
|
||||
self.think = fd_secret_move6;
|
||||
sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
|
||||
};
|
||||
|
||||
void () fd_secret_move6 =
|
||||
{
|
||||
sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
|
||||
SUB_CalcMove(self.oldorigin, self.speed, fd_secret_done);
|
||||
};
|
||||
|
||||
void () fd_secret_done =
|
||||
{
|
||||
if (!self.targetname || self.spawnflags&SECRET_YES_SHOOT)
|
||||
{
|
||||
self.health = 10000;
|
||||
self.takedamage = DAMAGE_YES;
|
||||
self.th_pain = fd_secret_pain;
|
||||
}
|
||||
sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
|
||||
};
|
||||
|
||||
void () secret_blocked =
|
||||
{
|
||||
if (time < self.attack_finished)
|
||||
return;
|
||||
self.attack_finished = time + 0.5;
|
||||
Damage (other, self, self, self.dmg);
|
||||
};
|
||||
|
||||
/*
|
||||
================
|
||||
secret_touch
|
||||
|
||||
Prints messages
|
||||
================
|
||||
*/
|
||||
void() secret_touch =
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
if (self.attack_finished > time)
|
||||
return;
|
||||
|
||||
self.attack_finished = time + 2;
|
||||
|
||||
if (self.message != "")
|
||||
{
|
||||
centerprint (other, self.message);
|
||||
sound (other, CHAN_BODY, "misc/talk.wav", 1, ATTN_NORM);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*QUAKED func_door_secret (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot
|
||||
Basic secret door. Slides back, then to the side. Angle determines direction.
|
||||
wait = # of seconds before coming back
|
||||
1st_left = 1st move is left of arrow
|
||||
1st_down = 1st move is down from arrow
|
||||
always_shoot = even if targeted, keep shootable
|
||||
t_width = override WIDTH to move back (or height if going down)
|
||||
t_length = override LENGTH to move sideways
|
||||
"dmg" damage to inflict when blocked (2 default)
|
||||
|
||||
If a secret door has a targetname, it will only be opened by it's botton or trigger, not by damage.
|
||||
"sounds"
|
||||
1) medieval
|
||||
2) metal
|
||||
3) base
|
||||
*/
|
||||
|
||||
void () func_door_secret =
|
||||
{
|
||||
if (self.sounds == 0)
|
||||
self.sounds = 3;
|
||||
if (self.sounds == 1)
|
||||
{
|
||||
precache_sound ("doors/latch2.wav");
|
||||
precache_sound ("doors/winch2.wav");
|
||||
precache_sound ("doors/drclos4.wav");
|
||||
self.noise1 = "doors/latch2.wav";
|
||||
self.noise2 = "doors/winch2.wav";
|
||||
self.noise3 = "doors/drclos4.wav";
|
||||
}
|
||||
if (self.sounds == 2)
|
||||
{
|
||||
precache_sound ("doors/airdoor1.wav");
|
||||
precache_sound ("doors/airdoor2.wav");
|
||||
self.noise2 = "doors/airdoor1.wav";
|
||||
self.noise1 = "doors/airdoor2.wav";
|
||||
self.noise3 = "doors/airdoor2.wav";
|
||||
}
|
||||
if (self.sounds == 3)
|
||||
{
|
||||
precache_sound ("doors/basesec1.wav");
|
||||
precache_sound ("doors/basesec2.wav");
|
||||
self.noise2 = "doors/basesec1.wav";
|
||||
self.noise1 = "doors/basesec2.wav";
|
||||
self.noise3 = "doors/basesec2.wav";
|
||||
}
|
||||
|
||||
if (!self.dmg)
|
||||
self.dmg = 2;
|
||||
|
||||
self.colour = 192;
|
||||
|
||||
// Magic formula...
|
||||
self.mangle = self.angles;
|
||||
self.angles = '0 0 0';
|
||||
self.solid = SOLID_BSP;
|
||||
self.movetype = MOVETYPE_PUSH;
|
||||
self.classname = "door";
|
||||
setmodel (self, self.model);
|
||||
setorigin (self, self.origin);
|
||||
|
||||
self.touch = secret_touch;
|
||||
self.blocked = secret_blocked;
|
||||
self.speed = 50;
|
||||
self.use = fd_secret_use;
|
||||
if ( !self.targetname || self.spawnflags&SECRET_YES_SHOOT)
|
||||
{
|
||||
self.health = 10000;
|
||||
self.takedamage = DAMAGE_YES;
|
||||
self.th_pain = fd_secret_pain;
|
||||
self.th_die = fd_secret_die;
|
||||
}
|
||||
self.oldorigin = self.origin;
|
||||
if (!self.wait)
|
||||
self.wait = 5; // 5 seconds before closing
|
||||
};
|
||||
422
mod_slipgate/source/server/fight.qc
Normal file
422
mod_slipgate/source/server/fight.qc
Normal file
@@ -0,0 +1,422 @@
|
||||
|
||||
/*
|
||||
|
||||
A monster is in fight mode if it thinks it can effectively attack its
|
||||
enemy.
|
||||
|
||||
When it decides it can't attack, it goes into hunt mode.
|
||||
|
||||
*/
|
||||
|
||||
float(float v) anglemod;
|
||||
|
||||
void() knight_atk1;
|
||||
void() knight_runatk1;
|
||||
void() ogre_smash1;
|
||||
void() ogre_swing1;
|
||||
|
||||
void() sham_smash1;
|
||||
void() sham_swingr1;
|
||||
void() sham_swingl1;
|
||||
|
||||
float() DemonCheckAttack;
|
||||
void(float side) Demon_Melee;
|
||||
|
||||
|
||||
void() ai_face;
|
||||
|
||||
|
||||
float enemy_vis, enemy_infront, enemy_range;
|
||||
float enemy_yaw;
|
||||
|
||||
entity sight_entity;
|
||||
float sight_entity_time;
|
||||
|
||||
.vector enemy_last;
|
||||
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
===========
|
||||
CheckAttack
|
||||
|
||||
The player is in view, so decide to move or launch an attack
|
||||
Returns FALSE if movement should continue
|
||||
============
|
||||
*/
|
||||
float() CheckAttack =
|
||||
{
|
||||
local vector spot1, spot2;
|
||||
local entity targ;
|
||||
local float chance;
|
||||
|
||||
targ = self.enemy;
|
||||
|
||||
// see if any entities are in the way of the shot
|
||||
spot1 = self.origin + self.view_ofs;
|
||||
spot2 = targ.origin + targ.view_ofs;
|
||||
|
||||
traceline (spot1, spot2, FALSE, self);
|
||||
|
||||
if (trace_ent != targ)
|
||||
return FALSE; // don't have a clear shot
|
||||
|
||||
if (trace_inopen && trace_inwater)
|
||||
return FALSE; // sight line crossed contents
|
||||
|
||||
if (enemy_range == RANGE_MELEE)
|
||||
{ // melee attack
|
||||
if (self.th_melee)
|
||||
{
|
||||
self.th_melee ();
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// missile attack
|
||||
if (!self.th_missile)
|
||||
return FALSE;
|
||||
|
||||
if (time < self.attack_finished)
|
||||
return FALSE;
|
||||
|
||||
if (enemy_range == RANGE_FAR)
|
||||
return FALSE;
|
||||
|
||||
if (enemy_range == RANGE_MELEE)
|
||||
{
|
||||
chance = 0.9;
|
||||
self.attack_finished = 0;
|
||||
}
|
||||
else if (enemy_range == RANGE_NEAR)
|
||||
{
|
||||
if (self.th_melee)
|
||||
chance = 0.2;
|
||||
else
|
||||
chance = 0.4;
|
||||
}
|
||||
else if (enemy_range == RANGE_MID)
|
||||
{
|
||||
if (self.th_melee)
|
||||
chance = 0.05;
|
||||
else
|
||||
chance = 0.1;
|
||||
}
|
||||
else
|
||||
chance = 0;
|
||||
|
||||
if (random () < chance)
|
||||
{
|
||||
self.th_missile ();
|
||||
SUB_AttackFinished (2*random());
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
ai_face
|
||||
|
||||
Stay facing the enemy
|
||||
=============
|
||||
*/
|
||||
void() ai_face =
|
||||
{
|
||||
self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
|
||||
changeyaw();
|
||||
};
|
||||
|
||||
void() ai_face_last =
|
||||
{
|
||||
self.ideal_yaw = vectoyaw(self.enemy_last - self.origin);
|
||||
changeyaw();
|
||||
};
|
||||
|
||||
/*
|
||||
=============
|
||||
ai_charge
|
||||
|
||||
The monster is in a melee attack, so get as close as possible to .enemy
|
||||
=============
|
||||
*/
|
||||
float (entity targ) visible;
|
||||
float(entity targ) infront;
|
||||
float(entity targ) range;
|
||||
|
||||
void(float d) ai_charge =
|
||||
{
|
||||
ai_face ();
|
||||
walkmove(self.angles_y, d);
|
||||
};
|
||||
|
||||
void() ai_charge_side =
|
||||
{
|
||||
local vector dtemp;
|
||||
local float heading;
|
||||
|
||||
// aim to the left of the enemy for a flyby
|
||||
|
||||
self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
|
||||
changeyaw ();
|
||||
|
||||
makevectors (self.angles);
|
||||
dtemp = self.enemy.origin - 30*v_right;
|
||||
heading = vectoyaw(dtemp - self.origin);
|
||||
|
||||
walkmove(heading, 20);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
ai_melee
|
||||
|
||||
=============
|
||||
*/
|
||||
void() ai_melee =
|
||||
{
|
||||
local vector delta;
|
||||
local float ldmg;
|
||||
|
||||
if (!self.enemy)
|
||||
return; // removed before stroke
|
||||
|
||||
delta = self.enemy.origin - self.origin;
|
||||
|
||||
if (vlen(delta) > 60)
|
||||
return;
|
||||
|
||||
ldmg = (random() + random() + random()) * 3;
|
||||
Damage (self.enemy, self, self, ldmg);
|
||||
};
|
||||
|
||||
|
||||
void() ai_melee_side =
|
||||
{
|
||||
local vector delta;
|
||||
local float ldmg;
|
||||
|
||||
if (!self.enemy)
|
||||
return; // removed before stroke
|
||||
|
||||
ai_charge_side();
|
||||
|
||||
delta = self.enemy.origin - self.origin;
|
||||
|
||||
if (vlen(delta) > 60)
|
||||
return;
|
||||
if (!CanDamage (self.enemy, self))
|
||||
return;
|
||||
ldmg = (random() + random() + random()) * 3;
|
||||
Damage (self.enemy, self, self, ldmg);
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
===========
|
||||
SoldierCheckAttack
|
||||
|
||||
The player is in view, so decide to move or launch an attack
|
||||
Returns FALSE if movement should continue
|
||||
============
|
||||
*/
|
||||
float() SoldierCheckAttack =
|
||||
{
|
||||
local vector spot1, spot2;
|
||||
local entity targ;
|
||||
local float chance;
|
||||
|
||||
targ = self.enemy;
|
||||
|
||||
// see if any entities are in the way of the shot
|
||||
spot1 = self.origin + self.view_ofs;
|
||||
spot2 = targ.origin + targ.view_ofs;
|
||||
|
||||
traceline (spot1, spot2, FALSE, self);
|
||||
|
||||
if (trace_inopen && trace_inwater)
|
||||
return FALSE; // sight line crossed contents
|
||||
|
||||
if (trace_ent != targ)
|
||||
return FALSE; // don't have a clear shot
|
||||
|
||||
|
||||
// missile attack
|
||||
if (time < self.attack_finished)
|
||||
return FALSE;
|
||||
|
||||
if (enemy_range == RANGE_FAR)
|
||||
return FALSE;
|
||||
|
||||
if (enemy_range == RANGE_MELEE)
|
||||
chance = 0.9;
|
||||
else if (enemy_range == RANGE_NEAR)
|
||||
chance = 0.4;
|
||||
else if (enemy_range == RANGE_MID)
|
||||
chance = 0.05;
|
||||
else
|
||||
chance = 0;
|
||||
|
||||
if (random () < chance)
|
||||
{
|
||||
self.attack_state = AS_MISSILE;
|
||||
SUB_AttackFinished (1 + random());
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
};
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
===========
|
||||
ShamCheckAttack
|
||||
|
||||
The player is in view, so decide to move or launch an attack
|
||||
Returns FALSE if movement should continue
|
||||
============
|
||||
*/
|
||||
float() ShamCheckAttack =
|
||||
{
|
||||
local vector spot1, spot2;
|
||||
local entity targ;
|
||||
//local float enemy_yaw;
|
||||
|
||||
if (enemy_range == RANGE_MELEE)
|
||||
{
|
||||
if (CanDamage (self.enemy, self))
|
||||
{
|
||||
self.attack_state = AS_MELEE;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (time < self.attack_finished)
|
||||
return FALSE;
|
||||
|
||||
if (!enemy_vis)
|
||||
return FALSE;
|
||||
|
||||
targ = self.enemy;
|
||||
|
||||
// see if any entities are in the way of the shot
|
||||
spot1 = self.origin + self.view_ofs;
|
||||
spot2 = targ.origin + targ.view_ofs;
|
||||
|
||||
if (vlen(spot1 - spot2) > 600)
|
||||
return FALSE;
|
||||
|
||||
traceline (spot1, spot2, FALSE, self);
|
||||
|
||||
if (trace_inopen && trace_inwater)
|
||||
return FALSE; // sight line crossed contents
|
||||
|
||||
if (trace_ent != targ)
|
||||
{
|
||||
return FALSE; // don't have a clear shot
|
||||
}
|
||||
|
||||
// missile attack
|
||||
if (enemy_range == RANGE_FAR)
|
||||
return FALSE;
|
||||
|
||||
self.attack_state = AS_MISSILE;
|
||||
SUB_AttackFinished (2 + 2*random());
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
/*
|
||||
===========
|
||||
OgreCheckAttack
|
||||
|
||||
The player is in view, so decide to move or launch an attack
|
||||
Returns FALSE if movement should continue
|
||||
============
|
||||
*/
|
||||
float() OgreCheckAttack =
|
||||
{
|
||||
if (enemy_range == RANGE_MELEE)
|
||||
{
|
||||
if (CanDamage (self.enemy, self))
|
||||
{
|
||||
self.attack_state = AS_MELEE;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (time < self.attack_finished)
|
||||
return FALSE;
|
||||
|
||||
// aim at last known location on hard and nightmare
|
||||
if (!enemy_vis)
|
||||
{
|
||||
if (skill > 1)
|
||||
{
|
||||
if (time < self.search_time)
|
||||
{
|
||||
vector spot1 = self.origin;
|
||||
vector spot2 = self.enemy_last;
|
||||
traceline(spot1, spot2, MOVE_MISSILE, self);
|
||||
if (trace_ent != world)
|
||||
if (trace_ent.solid != SOLID_BSP)
|
||||
return FALSE;
|
||||
|
||||
float chance = 0;
|
||||
if (vlen(self.origin - self.enemy_last) < 500)
|
||||
chance = 0.4;
|
||||
else
|
||||
chance = 0.1;
|
||||
if (random() < chance)
|
||||
{
|
||||
self.attack_state = AS_SPAM;
|
||||
SUB_AttackFinished (1 + 2*random());
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.attack_finished = time + 0.5;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
spot1 = self.origin;
|
||||
spot2 = self.enemy.origin + self.enemy.view_ofs;
|
||||
traceline (spot1, spot2, MOVE_MISSILE, self);
|
||||
if (trace_inwater)
|
||||
if (trace_inopen)
|
||||
return FALSE;
|
||||
if (trace_ent != self.enemy)
|
||||
return FALSE;
|
||||
|
||||
// missile attack
|
||||
chance = 0;
|
||||
if (enemy_range == RANGE_NEAR)
|
||||
chance = 0.5;
|
||||
else if (enemy_range == RANGE_MID)
|
||||
chance = 0.3;
|
||||
|
||||
if (random() < chance)
|
||||
{
|
||||
self.attack_state = AS_MISSILE;
|
||||
SUB_AttackFinished (1 + 2*random());
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.attack_finished = time + 0.5;
|
||||
return FALSE;
|
||||
}
|
||||
};
|
||||
240
mod_slipgate/source/server/fteqcc.ini
Normal file
240
mod_slipgate/source/server/fteqcc.ini
Normal file
@@ -0,0 +1,240 @@
|
||||
optimisation t default # c = a*b is performed in one operation rather than two, and can
|
||||
# cause older decompilers to fail.
|
||||
optimisation i default # if (!a) was traditionally compiled in two statements. This optimisation
|
||||
# does it in one, but can cause some decompilers to get confused.
|
||||
optimisation p default # In the original qcc, function parameters were specified as a vector
|
||||
# store even for floats. This fixes that.
|
||||
optimisation c default # This optimisation strips out the names of constants (but not strings)
|
||||
# from your progs, resulting in smaller files. It makes decompilers
|
||||
# leave out names or fabricate numerical ones.
|
||||
optimisation cs default # This optimisation strips out the names of string constants from
|
||||
# your progs. However, this can break addons, so don't use it in
|
||||
# those cases.
|
||||
optimisation d default # This will merge definitions of constants which are the same value.
|
||||
# Pay extra attention to assignment to constant warnings.
|
||||
optimisation s default # This will compact the string table that is stored in the progs.
|
||||
# It will be considerably smaller with this.
|
||||
optimisation l on # Strips out local names and definitions. Most decompiles will break
|
||||
# on this.
|
||||
optimisation n on # This strips out the names of functions which are never called.
|
||||
# Doesn't make much of an impact though.
|
||||
optimisation f on # This strips out the filenames of the progs. This can confuse the
|
||||
# really old decompilers, but is nothing to the more recent ones.
|
||||
optimisation u default # Removes the entries of unreferenced variables. Doesn't make a
|
||||
# difference in well maintained code.
|
||||
optimisation r default # Optimises the pr_globals count by overlapping temporaries. In
|
||||
# QC, every multiplication, division or operation in general produces
|
||||
# a temporary variable. This optimisation prevents excess, and in
|
||||
# the case of Hexen2's gamecode, reduces the count by 50k. This
|
||||
# is the most important optimisation, ever.
|
||||
optimisation a default # 5*6 actually emits an operation into the progs. This prevents
|
||||
# that happening, effectivly making the compiler see 30
|
||||
optimisation pf default # Strip out stuff wasted used in function calls and strings to the
|
||||
# precache_file builtin (which is actually a stub in quake).
|
||||
optimisation ro default # Functions ending in a return statement do not need a done statement
|
||||
# at the end of the function. This can confuse some decompilers,
|
||||
# making functions appear larger than they were.
|
||||
optimisation cj default # This optimisation plays an effect mostly with nested if/else statements,
|
||||
# instead of jumping to an unconditional jump statement, it'll jump
|
||||
# to the final destination instead. This will bewilder decompilers.
|
||||
optimisation sf default # Strips out the 'defs' of functions that were only ever called
|
||||
# directly. This does not affect saved games, but will prevent FTE_MULTIPROGS/mutators
|
||||
# from being able to hook functions.
|
||||
optimisation lo default # Store all locals in a single section of the pr_globals. Vastly
|
||||
# reducing it. This effectivly does the job of overlaptemps.
|
||||
# However, locals are no longer automatically initialised to 0 (and
|
||||
# never were in the case of recursion, but at least then its the
|
||||
# same type).
|
||||
# If locals appear uninitialised, fteqcc will disable this optimisation
|
||||
# for the affected functions, you can optionally get a warning about
|
||||
# these locals using: #pragma warning enable F302
|
||||
optimisation vc default # Where a function is called with just a vector, this causes the
|
||||
# function call to store three floats instead of one vector. This
|
||||
# can save a good number of pr_globals where those vectors contain
|
||||
# many duplicate coordinates but do not match entirly.
|
||||
optimisation cf default # Strip class field names. This will harm debugging and can result
|
||||
# in 'gibberish' names appearing in saved games. Has no effect on
|
||||
# engines other than FTEQW, which will not recognise these anyway.
|
||||
optimisation uf default # Strips any fields that have no references. This may result in
|
||||
# extra warnings at load time, or disabling support for mapper-specified
|
||||
# alpha in engines that do not provide that. FIXME: this is a little
|
||||
# pointless until relocs are properly implemented.
|
||||
keyword asm true # Disables the 'asm' keyword. Use the writeasm flag to see an example
|
||||
# of the asm.
|
||||
keyword break true # Disables the 'break' keyword.
|
||||
keyword case true # Disables the 'case' keyword.
|
||||
keyword class true # Disables the 'class' keyword.
|
||||
keyword const true # Disables the 'const' keyword.
|
||||
keyword continue true # Disables the 'continue' keyword.
|
||||
keyword default true # Disables the 'default' keyword.
|
||||
keyword entity true # Disables the 'entity' keyword.
|
||||
keyword enum true # Disables the 'enum' keyword.
|
||||
keyword enumflags true # Disables the 'enumflags' keyword.
|
||||
keyword extern true # Disables the 'extern' keyword. Use only on functions inside addons.
|
||||
keyword float true # Disables the 'float' keyword. (Disables the float keyword without
|
||||
# 'local' preceeding it)
|
||||
keyword for true # Disables the 'for' keyword. Syntax: for(assignment; while; increment)
|
||||
# {codeblock;}
|
||||
keyword goto true # Disables the 'goto' keyword.
|
||||
keyword int true # Disables the 'int' keyword.
|
||||
keyword integer true # Disables the 'integer' keyword.
|
||||
keyword noref true # Disables the 'noref' keyword.
|
||||
keyword unused false # Disables the 'unused' keyword. 'unused' means that the variable
|
||||
# is unused, you're aware that its unused, and you'd rather not
|
||||
# know about all the warnings this results in.
|
||||
keyword used false # Disables the 'used' keyword. 'used' means that the variable is
|
||||
# used even if the qcc can't see how - thus preventing it from ever
|
||||
# being stripped.
|
||||
keyword static true # Disables the 'static' keyword. 'static' means that a variable
|
||||
# has altered scope. On globals, the variable is visible only to
|
||||
# the current .qc file. On locals, the variable's value does not
|
||||
# change between calls to the function. On class variables, specifies
|
||||
# that the field is a scoped global instead of a local. On class
|
||||
# functions, specifies that 'this' is expected to be invalid and
|
||||
# that the function will access any memembers via it.
|
||||
keyword nonstatic true # Disables the 'nonstatic' keyword. 'nonstatic' acts upon globals+functions,
|
||||
# reverting the defaultstatic pragma on a per-variable basis. For
|
||||
# use by people who prefer to keep their APIs explicit.
|
||||
keyword ignore false # Disables the 'ignore' keyword. 'ignore' is expected to typically
|
||||
# be hidden behind a 'csqconly' define, and in such a context can
|
||||
# be used to conditionally compile functions a little more gracefully.
|
||||
# The opposite of the 'used' keyword. These variables/functions/members
|
||||
# are ALWAYS stripped, and effectively ignored.
|
||||
keyword nosave true # Disables the 'nosave' keyword.
|
||||
keyword inline true # Disables the 'inline' keyword.
|
||||
keyword strip true # Disables the 'strip' keyword.
|
||||
keyword shared true # Disables the 'shared' keyword.
|
||||
keyword state false # Disables the 'state' keyword.
|
||||
keyword optional true # Disables the 'optional' keyword.
|
||||
keyword inout false # Disables the 'inout' keyword.
|
||||
keyword string true # Disables the 'string' keyword.
|
||||
keyword struct true # Disables the 'struct' keyword.
|
||||
keyword switch true # Disables the 'switch' keyword.
|
||||
keyword thinktime false # Disables the 'thinktime' keyword which is used in HexenC
|
||||
keyword until false # Disables the 'until' keyword which is used in HexenC
|
||||
keyword loop false # Disables the 'loop' keyword which is used in HexenC
|
||||
keyword typedef true # Disables the 'typedef' keyword.
|
||||
keyword union true # Disables the 'union' keyword.
|
||||
keyword var true # Disables the 'var' keyword.
|
||||
keyword vector true # Disables the 'vector' keyword.
|
||||
keyword wrap true # Disables the 'wrap' keyword.
|
||||
keyword weak true # Disables the 'weak' keyword.
|
||||
keyword accumulate false # Disables the 'accumulate' keyword.
|
||||
flag acc false # Reacc is a pascall like compiler. It was released before the Quake
|
||||
# source was released. This flag has a few effects. It sorts all
|
||||
# qc files in the current directory into alphabetical order to compile
|
||||
# them. It also allows Reacc global/field distinctions, as well
|
||||
# as allows | for linebreaks. Whilst case insensitivity and lax
|
||||
# type checking are supported by reacc, they are seperate compiler
|
||||
# flags in fteqcc.
|
||||
flag qccx false # WARNING: This syntax makes mods inherantly engine specific.
|
||||
# Do NOT use unless you know what you're doing.This is provided
|
||||
# for compatibility only
|
||||
# Any entity hacks will be unsupported in FTEQW, DP, and others,
|
||||
# resulting in engine crashes if the code in question is executed.
|
||||
flag kce true # If you want keywords to NOT be disabled when they a variable by
|
||||
# the same name is defined, check here.
|
||||
flag parms false # if PARM0 PARM1 etc should be defined by the compiler. These are
|
||||
# useful if you make use of the asm keyword for function calls,
|
||||
# or you wish to create your own variable arguments. This is an
|
||||
# easy way to break decompilers.
|
||||
flag autoproto false # Causes compilation to take two passes instead of one. The first
|
||||
# pass, only the definitions are read. The second pass actually
|
||||
# compiles your code. This means you never have to remember to prototype
|
||||
# functions again.
|
||||
flag wasm false # Writes out a qc.asm which contains all your functions but in assembler.
|
||||
# This is a great way to look for bugs in fteqcc, but can also be
|
||||
# used to see exactly what your functions turn into, and thus how
|
||||
# to optimise statements better.
|
||||
flag annotate false # Annotate source code with assembler statements on compile (requires
|
||||
# gui).
|
||||
flag nullemptystr false # Empty string immediates will have the raw value 0 instead of 1.
|
||||
flag ifstring false # Causes if(string) to behave identically to if(string!=) This is
|
||||
# most useful with addons of course, but also has adverse effects
|
||||
# with FRIK_FILE's fgets, where it becomes impossible to determin
|
||||
# the end of the file. In such a case, you can still use asm {IF
|
||||
# string 2;RETURN} to detect eof and leave the function.
|
||||
flag iffloat false # Fixes certain floating point logic.
|
||||
flag ifvector true # Fixes conditional vector logic.
|
||||
flag vectorlogic true # Fixes conditional vector logic.
|
||||
flag brokenarray false # Treat references to arrays as references to the first index of
|
||||
# said array, to replicate an old fteqcc bug.
|
||||
flag rootconstructor false # When enabled, the root constructor should be called first like
|
||||
# in c++.
|
||||
flag caseinsens false # Causes fteqcc to become case insensitive whilst compiling names.
|
||||
# It's generally not advised to use this as it compiles a little
|
||||
# more slowly and provides little benefit. However, it is required
|
||||
# for full reacc support.
|
||||
flag lax false # Disables many errors (generating warnings instead) when function
|
||||
# calls or operations refer to two normally incompatible types.
|
||||
# This is required for reacc support, and can also allow certain
|
||||
# (evil) mods to compile that were originally written for frikqcc.
|
||||
flag hashonly false # Allows use of only #constant for precompiler constants, allows
|
||||
# certain preqcc using mods to compile
|
||||
flag lo false # This changes the behaviour of your code. It generates additional
|
||||
# if operations to early-out in if statements. With this flag, the
|
||||
# line if (0 && somefunction()) will never call the function. It
|
||||
# can thus be considered an optimisation. However, due to the change
|
||||
# of behaviour, it is not considered so by fteqcc. Note that due
|
||||
# to inprecisions with floats, this flag can cause runaway loop
|
||||
# errors within the player walk and run functions (without iffloat
|
||||
# also enabled). This code is advised:
|
||||
# player_stand1:
|
||||
# if (self.velocity_x || self.velocity_y)
|
||||
# player_run
|
||||
# if (!(self.velocity_x || self.velocity_y))
|
||||
flag msvcstyle false # Generates warning and error messages in a format that msvc understands,
|
||||
# to facilitate ide integration.
|
||||
flag debugmacros false # Print out the contents of macros that are expanded. This can help
|
||||
# look inside macros that are expanded and is especially handy if
|
||||
# people are using preprocessor hacks.
|
||||
flag filetimes false # Recompiles the progs only if the file times are modified.
|
||||
flag fastarrays false # Generates extra instructions inside array handling functions to
|
||||
# detect engine and use extension opcodes only in supporting engines.
|
||||
# Adds a global which is set by the engine if the engine supports
|
||||
# the extra opcodes. Note that this applies to all arrays or none.
|
||||
flag assumeint false # Numerical constants are assumed to be integers, instead of floats.
|
||||
flag subscope false # Restrict the scope of locals to the block they are actually defined
|
||||
# within, as in C.
|
||||
flag verbose false # Lots of extra compiler messages.
|
||||
flag typeexplicit false # All type conversions must be explicit or directly supported by
|
||||
# instruction set.
|
||||
flag boundchecks true # Disable array index checks, speeding up array access but can result
|
||||
# in your code misbehaving.
|
||||
flag attributes false # WARNING: This syntax conflicts with vector constructors.
|
||||
flag assumevar false # Initialised globals will be considered non-const by default.
|
||||
flag ssp false # Treat ** as an operator for exponents, instead of multiplying
|
||||
# by a dereferenced pointer.
|
||||
flag cpriority false # QC treats !a&&b as equivelent to !(a&&b). When this is set, behaviour
|
||||
# will be (!a)&&b as in C. Other operators are also affected in
|
||||
# similar ways.
|
||||
flag allowuninit false # Permit optimisations that may result in locals being uninitialised.
|
||||
# This may allow for greater reductions in temps.
|
||||
flag nofileline false # Ignores #pragma file(foo) and #pragma line(foo), so that errors
|
||||
# and symbols reflect the actual lines, instead of the original
|
||||
# source.
|
||||
flag utf8 false # String immediates will use utf-8 encoding, instead of quake's
|
||||
# encoding.
|
||||
flag embedsrc false # Write the sourcecode into the output file. The resulting .dat
|
||||
# can be opened as a standard zip archive (or by fteqccgui).
|
||||
# Good for GPL compliance!
|
||||
showall off # Show all keyword options in the gui
|
||||
compileonstart off # Recompile on GUI startup
|
||||
log off # Write out a compile log
|
||||
enginebinary fteqw.exe # Location of the engine binary to run. Change this to something
|
||||
# else to run a different engine, but not all support debugging.
|
||||
basedir ../.. # The base directory of the game that contains your sub directory
|
||||
engineargs "-window -game waypoint +developer 1 +map test"
|
||||
# The engine commandline to use when debugging. You'll likely want
|
||||
# to ensure this contains -window as well as the appropriate -game
|
||||
# argument.
|
||||
srcfile progs.src # The progs.src file to load to find ordering of other qc files.
|
||||
src # Additional subdir to read qc files from. Typically blank (ie:
|
||||
# the working directory).
|
||||
tabsize 8 # Specifies the size of tabs in scintilla windows.
|
||||
extramargins off # Enables line number and folding margins.
|
||||
hexen2 off # Enable the extra tweaks needed for compatibility with hexen2 engines.
|
||||
extendedopcodes off # Utilise an extended instruction set, providing support for pointers
|
||||
# and faster arrays and other speedups.
|
||||
parameters # Other additional parameters that are not supported by the gui.
|
||||
# Likely including -DFOO
|
||||
165
mod_slipgate/source/server/gore.qc
Normal file
165
mod_slipgate/source/server/gore.qc
Normal file
@@ -0,0 +1,165 @@
|
||||
/*==========
|
||||
GibTouch
|
||||
|
||||
squelch, splat
|
||||
==========*/
|
||||
static void() GibTouch =
|
||||
{
|
||||
if (other != world)
|
||||
return;
|
||||
// don't sound more than once per gib
|
||||
if (self.count)
|
||||
return;
|
||||
// don't always sound
|
||||
if (random() < 0.5)
|
||||
return;
|
||||
self.count = 1;
|
||||
float r = random();
|
||||
if (r < 0.2)
|
||||
sound (self, CHAN_VOICE, "zombie/z_miss.wav", 0.5, ATTN_IDLE);
|
||||
else
|
||||
sound (self, CHAN_VOICE, "player/tornoff2.wav", 0.5, ATTN_IDLE);
|
||||
};
|
||||
|
||||
/*==========
|
||||
GibVelocity
|
||||
==========*/
|
||||
static vector(float dm) GibVelocity =
|
||||
{
|
||||
vector v = [100 * crandom(), 100 * crandom(), 200 + 100 * random()];
|
||||
if (dm > -50)
|
||||
return v * 0.7;
|
||||
else if (dm > -200)
|
||||
return v * 2;
|
||||
else
|
||||
return v * 10;
|
||||
};
|
||||
|
||||
/*==========
|
||||
SpawnGib
|
||||
==========*/
|
||||
void(string gibname) SpawnGib =
|
||||
{
|
||||
entity gib = spawn();
|
||||
gib.classname = "gib";
|
||||
gib.owner = self;
|
||||
gib.solid = SOLID_TRIGGER;
|
||||
gib.movetype = MOVETYPE_BOUNCE;
|
||||
setmodel (gib, gibname);
|
||||
setsize (gib, '0 0 0', '0 0 0');
|
||||
|
||||
vector org = self.origin;
|
||||
setorigin (gib, [org_x + crandom() * 0.5 * self.size_x, org_y + crandom() * 0.5 * self.size_y, org_z + crandom() * 0.5 * self.size_z]);
|
||||
gib.velocity = GibVelocity(self.health);
|
||||
gib.avelocity = randomvec() * 100;
|
||||
gib.frame = randomrange(10);
|
||||
|
||||
gib.touch = GibTouch;
|
||||
gib.think = SUB_Remove;
|
||||
gib.nextthink = time + 10 + random() * 10;
|
||||
};
|
||||
|
||||
/*==========
|
||||
GibSound
|
||||
==========*/
|
||||
static void() GibSound =
|
||||
{
|
||||
float r = randomrange(4);
|
||||
|
||||
// player death sounds have no attenuation
|
||||
float attn;
|
||||
if (self.classname == "player")
|
||||
attn = ATTN_NONE;
|
||||
else
|
||||
attn = ATTN_NORM;
|
||||
|
||||
if (r == 0)
|
||||
sound (self, CHAN_VOICE, "player/udeath.wav", 1, attn);
|
||||
else if (r == 1)
|
||||
sound (self, CHAN_VOICE, "player/teledth1.wav", 1, attn);
|
||||
else if (r == 2)
|
||||
sound (self, CHAN_VOICE, "player/gib.wav", 1, attn);
|
||||
else if (r == 4)
|
||||
sound (self, CHAN_VOICE, "player/tornoff2.wav", 1, attn);
|
||||
};
|
||||
|
||||
/*==========
|
||||
BecomeGibs
|
||||
==========*/
|
||||
void() BecomeGibs =
|
||||
{
|
||||
GibSound();
|
||||
|
||||
self.think = SUB_Null;
|
||||
self.nextthink = -1;
|
||||
self.deadflag = DEAD_DEAD;
|
||||
self.takedamage = DAMAGE_NO;
|
||||
self.frame = 0;
|
||||
self.flags = self.flags - (self.flags & FL_ONGROUND);
|
||||
|
||||
self.solid = SOLID_NOT;
|
||||
self.movetype = MOVETYPE_BOUNCE;
|
||||
setmodel (self, self.headmodel);
|
||||
setsize (self, '-16 -16 0', '16 16 16');
|
||||
setorigin(self, self.origin + self.view_ofs + '0 0 8');
|
||||
self.view_ofs = '0 0 8';
|
||||
|
||||
self.velocity = GibVelocity(self.health);
|
||||
self.avelocity = [0, crandom() * 600, 0];
|
||||
};
|
||||
|
||||
/*==========
|
||||
SpawnMeatSpray
|
||||
==========*/
|
||||
void(vector org, vector vel) SpawnMeatSpray =
|
||||
{
|
||||
entity gib = spawn();
|
||||
gib.classname = "gib";
|
||||
gib.owner = self;
|
||||
gib.solid = SOLID_NOT;
|
||||
gib.movetype = MOVETYPE_TOSS;
|
||||
setmodel (gib, "progs/zom_gib.mdl");
|
||||
setsize (gib, '0 0 0', '0 0 0');
|
||||
setorigin (gib, org);
|
||||
|
||||
gib.velocity = vel;
|
||||
gib.velocity_z = gib.velocity_z + 250 + 50 * random();
|
||||
gib.avelocity = '3000 1000 2000';
|
||||
|
||||
gib.touch = SUB_Remove;
|
||||
gib.think = SUB_Remove;
|
||||
gib.nextthink = time + 1;
|
||||
};
|
||||
|
||||
/*==========
|
||||
SpawnBlood
|
||||
==========*/
|
||||
void(vector org, vector vel, float damage) SpawnBlood =
|
||||
{
|
||||
particle(org, vel, 66, damage);
|
||||
particle(org, vel, 73, damage);
|
||||
};
|
||||
|
||||
/*==========
|
||||
SpawnTouchParticles
|
||||
==========*/
|
||||
void(float damage, float col) SpawnTouchParticles =
|
||||
{
|
||||
vector vel = normalize(self.velocity);
|
||||
vector org = self.origin - 4 * vel;
|
||||
|
||||
makevectors(vel);
|
||||
vel = v_right * crandom() + v_up * crandom();
|
||||
vel = vel * random() * 4;
|
||||
|
||||
particle(org, vel, col, damage);
|
||||
};
|
||||
|
||||
/*==========
|
||||
SpawnTouchblood
|
||||
==========*/
|
||||
void(float damage) SpawnTouchblood =
|
||||
{
|
||||
SpawnTouchParticles(damage, 66);
|
||||
SpawnTouchParticles(damage, 73);
|
||||
};
|
||||
77
mod_slipgate/source/server/info.qc
Normal file
77
mod_slipgate/source/server/info.qc
Normal file
@@ -0,0 +1,77 @@
|
||||
/*QUAKED info_null (.5 .5 .5) (-8 -8 -8) (8 8 8)
|
||||
Used as a positional target for spotlights, etc.
|
||||
*/
|
||||
void() info_null =
|
||||
{
|
||||
remove(self);
|
||||
};
|
||||
|
||||
/*==========
|
||||
info_notnull
|
||||
|
||||
bad maphack, bad!
|
||||
==========*/
|
||||
void() info_notnull =
|
||||
{
|
||||
remove(self);
|
||||
};
|
||||
|
||||
/*QUAKED info_intermission (1 0.5 0.5) (-8 -8 -8) (8 8 8)
|
||||
This is the camera point for the intermission.
|
||||
Use mangle instead of angle, so you can set pitch and roll as well as yaw.
|
||||
*/
|
||||
void() info_intermission = {};
|
||||
|
||||
/*QUAKED info_player_start (0 .5 0) (-16 -16 -24) (16 16 32)
|
||||
{
|
||||
model ({"path" : "progs/player.mdl", "frame" : 12});
|
||||
}
|
||||
The normal starting point for a level.
|
||||
*/
|
||||
void() info_player_start = {};
|
||||
|
||||
/*QUAKED info_player_start2 (0 .5 0) (-16 -16 -24) (16 16 32)
|
||||
{
|
||||
model ({"path" : "progs/player.mdl", "frame" : 12});
|
||||
}
|
||||
Used as the return point from an episode. Players will spawn here if they have any runes.
|
||||
*/
|
||||
void() info_player_start2 = {};
|
||||
|
||||
/*QUAKED info_player_test (0 .5 0) (-16 -16 -24) (16 16 32)
|
||||
{
|
||||
model ({"path" : "progs/player.mdl", "frame" : 12});
|
||||
}
|
||||
For debugging only. If developer mode is active, player will always spawn here.
|
||||
*/
|
||||
void() info_player_test = {};
|
||||
|
||||
/*QUAKED info_player_deathmatch (0 .5 0) (-16 -16 -24) (16 16 32)
|
||||
{
|
||||
model ({"path" : "progs/player.mdl", "frame" : 12});
|
||||
}
|
||||
Spawning position for deathmatch games.
|
||||
*/
|
||||
void() info_player_deathmatch = {};
|
||||
|
||||
/*QUAKED info_player_coop (0 .5 0) (-16 -16 -24) (16 16 32)
|
||||
{
|
||||
model ({"path" : "progs/player.mdl", "frame" : 12});
|
||||
}
|
||||
Spawning position for coop games.
|
||||
*/
|
||||
void() info_player_coop = {};
|
||||
|
||||
/*QUAKED info_teleport_destination (.5 .5 .5) (-16 -16 0) (16 16 56)
|
||||
This is the destination marker for a teleporter.
|
||||
It should have a "targetname" field with the same value as a trigger_teleport "target" field.
|
||||
Set "angle" to the direction the player should face when arriving at the destination.
|
||||
*/
|
||||
void() info_teleport_destination =
|
||||
{
|
||||
if (!self.targetname)
|
||||
{
|
||||
objerror ("no targetname");
|
||||
remove(self);
|
||||
}
|
||||
};
|
||||
223
mod_slipgate/source/server/intermission.qc
Normal file
223
mod_slipgate/source/server/intermission.qc
Normal file
@@ -0,0 +1,223 @@
|
||||
/*==========
|
||||
GotoNextMap
|
||||
========*/
|
||||
void() GotoNextMap =
|
||||
{
|
||||
if (cvar("samelevel") && (deathmatch || coop))
|
||||
changelevel (mapname);
|
||||
else
|
||||
changelevel (nextmap);
|
||||
};
|
||||
|
||||
/*==========
|
||||
ExitIntermission
|
||||
==========*/
|
||||
void() ExitIntermission =
|
||||
{
|
||||
if (deathmatch)
|
||||
{
|
||||
GotoNextMap();
|
||||
return;
|
||||
}
|
||||
|
||||
intermission_exittime = time + 1;
|
||||
intermission_running = intermission_running + 1;
|
||||
|
||||
//
|
||||
// run some text if at the end of an episode
|
||||
//
|
||||
if (intermission_running == 2)
|
||||
{
|
||||
if (world.model == "maps/e1m7.bsp")
|
||||
{
|
||||
WriteByte (MSG_ALL, SVC_CDTRACK);
|
||||
WriteByte (MSG_ALL, 2);
|
||||
WriteByte (MSG_ALL, 3);
|
||||
if (!cvar("registered"))
|
||||
{
|
||||
WriteByte (MSG_ALL, SVC_FINALE);
|
||||
WriteString (MSG_ALL, "As the corpse of the monstrous entity\nChthon sinks back into the lava whence\nit rose, you grip the Rune of Earth\nMagic tightly. Now that you have\nconquered the Dimension of the Doomed,\nrealm of Earth Magic, you are ready to\ncomplete your task in the other three\nhaunted lands of Quake. Or are you? If\nyou don't register Quake, you'll never\nknow what awaits you in the Realm of\nBlack Magic, the Netherworld, and the\nElder World!");
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteByte (MSG_ALL, SVC_FINALE);
|
||||
WriteString (MSG_ALL, "As the corpse of the monstrous entity\nChthon sinks back into the lava whence\nit rose, you grip the Rune of Earth\nMagic tightly. Now that you have\nconquered the Dimension of the Doomed,\nrealm of Earth Magic, you are ready to\ncomplete your task. A Rune of magic\npower lies at the end of each haunted\nland of Quake. Go forth, seek the\ntotality of the four Runes!");
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (world.model == "maps/e2m6.bsp")
|
||||
{
|
||||
WriteByte (MSG_ALL, SVC_CDTRACK);
|
||||
WriteByte (MSG_ALL, 2);
|
||||
WriteByte (MSG_ALL, 3);
|
||||
|
||||
WriteByte (MSG_ALL, SVC_FINALE);
|
||||
WriteString (MSG_ALL, "The Rune of Black Magic throbs evilly in\nyour hand and whispers dark thoughts\ninto your brain. You learn the inmost\nlore of the Hell-Mother; Shub-Niggurath!\nYou now know that she is behind all the\nterrible plotting which has led to so\nmuch death and horror. But she is not\ninviolate! Armed with this Rune, you\nrealize that once all four Runes are\ncombined, the gate to Shub-Niggurath's\nPit will open, and you can face the\nWitch-Goddess herself in her frightful\notherworld cathedral.");
|
||||
return;
|
||||
}
|
||||
else if (world.model == "maps/e3m6.bsp")
|
||||
{
|
||||
WriteByte (MSG_ALL, SVC_CDTRACK);
|
||||
WriteByte (MSG_ALL, 2);
|
||||
WriteByte (MSG_ALL, 3);
|
||||
|
||||
WriteByte (MSG_ALL, SVC_FINALE);
|
||||
WriteString (MSG_ALL, "The charred viscera of diabolic horrors\nbubble viscously as you seize the Rune\nof Hell Magic. Its heat scorches your\nhand, and its terrible secrets blight\nyour mind. Gathering the shreds of your\ncourage, you shake the devil's shackles\nfrom your soul, and become ever more\nhard and determined to destroy the\nhideous creatures whose mere existence\nthreatens the souls and psyches of all\nthe population of Earth.");
|
||||
return;
|
||||
}
|
||||
else if (world.model == "maps/e4m7.bsp")
|
||||
{
|
||||
WriteByte (MSG_ALL, SVC_CDTRACK);
|
||||
WriteByte (MSG_ALL, 2);
|
||||
WriteByte (MSG_ALL, 3);
|
||||
|
||||
WriteByte (MSG_ALL, SVC_FINALE);
|
||||
WriteString (MSG_ALL, "Despite the awful might of the Elder\nWorld, you have achieved the Rune of\nElder Magic, capstone of all types of\narcane wisdom. Beyond good and evil,\nbeyond life and death, the Rune\npulsates, heavy with import. Patient and\npotent, the Elder Being Shub-Niggurath\nweaves her dire plans to clear off all\nlife from the Earth, and bring her own\nfoul offspring to our world! For all the\ndwellers in these nightmare dimensions\nare her descendants! Once all Runes of\nmagic power are united, the energy\nbehind them will blast open the Gateway\nto Shub-Niggurath, and you can travel\nthere to foil the Hell-Mother's plots\nin person.");
|
||||
return;
|
||||
}
|
||||
|
||||
GotoNextMap();
|
||||
}
|
||||
|
||||
if (intermission_running == 3)
|
||||
{
|
||||
if (!cvar("registered"))
|
||||
{ // shareware episode has been completed, go to sell screen
|
||||
WriteByte (MSG_ALL, SVC_SELLSCREEN);
|
||||
return;
|
||||
}
|
||||
if ( (serverflags & 15) == 15)
|
||||
{
|
||||
WriteByte (MSG_ALL, SVC_FINALE);
|
||||
WriteString (MSG_ALL, "Now, you have all four Runes. You sense\ntremendous invisible forces moving to\nunseal ancient barriers. Shub-Niggurath\nhad hoped to use the Runes Herself to\nclear off the Earth, but now instead,\nyou will use them to enter her home and\nconfront her as an avatar of avenging\nEarth-life. If you defeat her, you will\nbe remembered forever as the savior of\nthe planet. If she conquers, it will be\nas if you had never been born.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
GotoNextMap();
|
||||
};
|
||||
|
||||
/*==========
|
||||
IntermissionChangeSpot
|
||||
==========*/
|
||||
static void() IntermissionChangeSpot =
|
||||
{
|
||||
if (!(self.flags & FL_JUMPRELEASED))
|
||||
return;
|
||||
self.flags = self.flags - FL_JUMPRELEASED;
|
||||
|
||||
// move to the next spot, if available
|
||||
entity nextspot = self.enemy.enemy;
|
||||
if (!nextspot)
|
||||
return;
|
||||
|
||||
self.enemy = nextspot;
|
||||
self.angles = self.v_angle = nextspot.mangle;
|
||||
self.fixangle = TRUE;
|
||||
setorigin (self, nextspot.origin);
|
||||
};
|
||||
|
||||
/*==========
|
||||
IntermissionThink
|
||||
|
||||
called by players from PlayerPreThink
|
||||
==========*/
|
||||
void() IntermissionThink =
|
||||
{
|
||||
if (self.button2)
|
||||
IntermissionChangeSpot();
|
||||
else
|
||||
self.flags = self.flags | FL_JUMPRELEASED;
|
||||
|
||||
if (time < intermission_exittime || intermission_exittime == -1)
|
||||
return;
|
||||
if (!self.button0)
|
||||
return;
|
||||
ExitIntermission();
|
||||
};
|
||||
|
||||
/*==========
|
||||
FindIntermission
|
||||
==========*/
|
||||
static entity() FindIntermission =
|
||||
{
|
||||
// count the number of intermission spots in the map,
|
||||
// and put them into a linked list
|
||||
float count = 0;
|
||||
entity first = world;
|
||||
entity last = world;
|
||||
entity spot = find(world, classname, "info_intermission");
|
||||
while (spot)
|
||||
{
|
||||
if (!first)
|
||||
first = spot;
|
||||
if (last != world)
|
||||
last.enemy = spot;
|
||||
last = spot;
|
||||
count = count + 1;
|
||||
spot = find(spot, classname, "info_intermission");
|
||||
}
|
||||
// no intermission spots found in map, so try and use player start instead
|
||||
if (!count)
|
||||
{
|
||||
spot = find (world, classname, "info_player_start");
|
||||
if (spot)
|
||||
return spot;
|
||||
error("no intermission spot found");
|
||||
}
|
||||
last.enemy = first; // make it a loop
|
||||
|
||||
// pick a random spot
|
||||
float pick = randomrange(count) + 1;
|
||||
spot = world;
|
||||
while (pick)
|
||||
{
|
||||
spot = find(spot, classname, "info_intermission");
|
||||
pick = pick - 1;
|
||||
}
|
||||
return spot;
|
||||
};
|
||||
|
||||
/*==========
|
||||
StartIntermission
|
||||
==========*/
|
||||
void() StartIntermission =
|
||||
{
|
||||
intermission_running = 1;
|
||||
|
||||
if (deathmatch)
|
||||
intermission_exittime = time + 5;
|
||||
else
|
||||
intermission_exittime = time + 2;
|
||||
|
||||
// change cd track
|
||||
WriteByte (MSG_ALL, SVC_CDTRACK);
|
||||
WriteByte (MSG_ALL, 3);
|
||||
WriteByte (MSG_ALL, 3);
|
||||
|
||||
// find the intermission spot and move all players to it
|
||||
entity pos = FindIntermission();
|
||||
other = find (world, classname, "player");
|
||||
while (other != world)
|
||||
{
|
||||
other.enemy = pos;
|
||||
other.view_ofs = '0 0 0';
|
||||
other.angles = other.v_angle = pos.mangle;
|
||||
other.fixangle = TRUE;
|
||||
other.think = SUB_Null;
|
||||
other.nextthink = time + 0.1;
|
||||
other.takedamage = DAMAGE_NO;
|
||||
other.solid = SOLID_NOT;
|
||||
other.movetype = MOVETYPE_NONE;
|
||||
// we have to use a null sprite, because the
|
||||
// server won't update players with no modelindex, and
|
||||
// we now support intermission spot cycling
|
||||
setmodel (other, "progs/s_null.spr");
|
||||
setsize (other, '0 0 0', '0 0 0');
|
||||
setorigin (other, pos.origin);
|
||||
other = find (other, classname, "player");
|
||||
}
|
||||
|
||||
// remove sbar and put up end of level stats
|
||||
WriteByte (MSG_ALL, SVC_INTERMISSION);
|
||||
};
|
||||
223
mod_slipgate/source/server/it_ammo.qc
Normal file
223
mod_slipgate/source/server/it_ammo.qc
Normal file
@@ -0,0 +1,223 @@
|
||||
static enumflags { AMMO_BIG };
|
||||
|
||||
/*==========
|
||||
ammo_touch
|
||||
==========*/
|
||||
static void() ammo_touch =
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
if (other.health <= 0)
|
||||
return;
|
||||
|
||||
float count = 0;
|
||||
if (self.items == IT_SHELLS)
|
||||
{
|
||||
if (other.ammo_shells >= 100)
|
||||
return;
|
||||
other.ammo_shells = other.ammo_shells + self.ammo_shells;
|
||||
count = self.ammo_shells;
|
||||
}
|
||||
if (self.items == IT_NAILS)
|
||||
{
|
||||
if (other.ammo_nails >= 200)
|
||||
return;
|
||||
other.ammo_nails = other.ammo_nails + self.ammo_nails;
|
||||
count = self.ammo_nails;
|
||||
}
|
||||
if (self.items == IT_ROCKETS)
|
||||
{
|
||||
if (other.ammo_rockets >= 100)
|
||||
return;
|
||||
other.ammo_rockets = other.ammo_rockets + self.ammo_rockets;
|
||||
count = self.ammo_rockets;
|
||||
}
|
||||
if (self.items == IT_CELLS)
|
||||
{
|
||||
if (other.ammo_cells >= 100)
|
||||
return;
|
||||
other.ammo_cells = other.ammo_cells + self.ammo_cells;
|
||||
count = self.ammo_cells;
|
||||
}
|
||||
W_BoundAmmo(other);
|
||||
W_SetCurrentAmmo(other);
|
||||
|
||||
sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
|
||||
stuffcmd (other, "bf\n");
|
||||
|
||||
sprint (other, "You got ");
|
||||
sprint (other, ftos(count));
|
||||
sprint (other, " ");
|
||||
sprint (other, self.netname);
|
||||
sprint (other, "\n");
|
||||
|
||||
self.model = string_null;
|
||||
self.solid = SOLID_NOT;
|
||||
if (deathmatch)
|
||||
{
|
||||
self.think = ItemRespawn;
|
||||
self.nextthink = time + 30;
|
||||
}
|
||||
|
||||
// fire all targets
|
||||
activator = other;
|
||||
UseTargets();
|
||||
};
|
||||
|
||||
/*QUAKED item_shells (0 0 1) (0 0 0) (32 32 56) AMMO_BIG X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ( {{ spawnflags & 1 -> { "path" : "maps/b_shell1.bsp" }, "maps/b_shell0.bsp" }} );
|
||||
}
|
||||
Nox of 20 shells.
|
||||
AMMO_BIG is a box of 40 shells.
|
||||
*/
|
||||
void() item_shells =
|
||||
{
|
||||
self.touch = ammo_touch;
|
||||
if (self.spawnflags & AMMO_BIG)
|
||||
{
|
||||
precache_model ("maps/b_shell1.bsp");
|
||||
setmodel (self, "maps/b_shell1.bsp");
|
||||
self.ammo_shells = 40;
|
||||
}
|
||||
else
|
||||
{
|
||||
precache_model ("maps/b_shell0.bsp");
|
||||
setmodel (self, "maps/b_shell0.bsp");
|
||||
self.ammo_shells = 20;
|
||||
}
|
||||
self.items = IT_SHELLS;
|
||||
self.netname = "shells";
|
||||
setsize (self, '0 0 0', '32 32 56');
|
||||
StartItem ();
|
||||
};
|
||||
|
||||
/*QUAKED item_spikes (0 0 1) (0 0 0) (32 32 56) AMMO_BIG X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ( {{ spawnflags & 1 -> { "path" : "maps/b_nail1.bsp" }, "maps/b_nail0.bsp" }} );
|
||||
}
|
||||
Nox of 25 nails.
|
||||
AMMO_BIG is a box of 50 nails.
|
||||
*/
|
||||
void() item_spikes =
|
||||
{
|
||||
self.touch = ammo_touch;
|
||||
if (self.spawnflags & AMMO_BIG)
|
||||
{
|
||||
precache_model ("maps/b_nail1.bsp");
|
||||
setmodel (self, "maps/b_nail1.bsp");
|
||||
self.ammo_nails = 50;
|
||||
}
|
||||
else
|
||||
{
|
||||
precache_model ("maps/b_nail0.bsp");
|
||||
setmodel (self, "maps/b_nail0.bsp");
|
||||
self.ammo_nails = 25;
|
||||
}
|
||||
self.items = IT_NAILS;
|
||||
self.netname = "nails";
|
||||
setsize (self, '0 0 0', '32 32 56');
|
||||
StartItem ();
|
||||
};
|
||||
|
||||
/*QUAKED item_rockets (0 0 1) (0 0 0) (32 32 56) AMMO_BIG X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ( {{ spawnflags & 1 -> { "path" : "maps/b_rock1.bsp" }, "maps/b_rock0.bsp" }} );
|
||||
}
|
||||
Nox of 5 rockets.
|
||||
AMMO_BIG is a box of 10 rockets.
|
||||
*/
|
||||
void() item_rockets =
|
||||
{
|
||||
self.touch = ammo_touch;
|
||||
if (self.spawnflags & AMMO_BIG)
|
||||
{
|
||||
precache_model ("maps/b_rock1.bsp");
|
||||
setmodel (self, "maps/b_rock1.bsp");
|
||||
self.ammo_rockets = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
precache_model ("maps/b_rock0.bsp");
|
||||
setmodel (self, "maps/b_rock0.bsp");
|
||||
self.ammo_rockets = 5;
|
||||
}
|
||||
self.items = IT_ROCKETS;
|
||||
self.netname = "rockets";
|
||||
setsize (self, '0 0 0', '32 32 56');
|
||||
StartItem ();
|
||||
};
|
||||
|
||||
/*QUAKED item_cells (0 0 1) (0 0 0) (32 32 56) AMMO_BIG X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ( {{ spawnflags & 1 -> { "path" : "maps/b_batt1.bsp" }, "maps/b_batt0.bsp" }} );
|
||||
}
|
||||
Nox of 6 cells.
|
||||
AMMO_BIG is a box of 12 cells.
|
||||
*/
|
||||
void() item_cells =
|
||||
{
|
||||
self.touch = ammo_touch;
|
||||
if (self.spawnflags & AMMO_BIG)
|
||||
{
|
||||
precache_model ("maps/b_batt1.bsp");
|
||||
setmodel (self, "maps/b_batt1.bsp");
|
||||
self.ammo_cells = 12;
|
||||
}
|
||||
else
|
||||
{
|
||||
precache_model ("maps/b_batt0.bsp");
|
||||
setmodel (self, "maps/b_batt0.bsp");
|
||||
self.ammo_cells = 6;
|
||||
}
|
||||
self.items = IT_CELLS;
|
||||
self.netname = "cells";
|
||||
setsize (self, '0 0 0', '32 32 56');
|
||||
StartItem ();
|
||||
};
|
||||
|
||||
/*==========
|
||||
item_weapon
|
||||
|
||||
Stupid remnant that is deprecated but used in id1 on dm5, dm6,
|
||||
e2m2 and e3m7. despite the name, it's an ammo box. the vanilla item
|
||||
contains a couple of bugs, for example nails are called spikes and don't
|
||||
match the ammo count of the normal item.
|
||||
prints a warning and converts itself to the correct entity upon spawn.
|
||||
==========*/
|
||||
static enumflags { ITW_SHELLS, ITW_ROCKETS, ITW_NAILS, ITW_BIG };
|
||||
void() item_weapon =
|
||||
{
|
||||
dprint("warning: item_weapon is deprecated!\n");
|
||||
|
||||
if (!(self.spawnflags & (ITW_SHELLS | ITW_ROCKETS | ITW_NAILS)))
|
||||
{
|
||||
objerror("invalid spawnflags");
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
|
||||
// convert into correct item
|
||||
|
||||
if (self.spawnflags & ITW_BIG)
|
||||
self.spawnflags = self.spawnflags - ITW_BIG + AMMO_BIG;
|
||||
|
||||
if (self.spawnflags & ITW_SHELLS)
|
||||
{
|
||||
self.spawnflags = self.spawnflags - ITW_SHELLS;
|
||||
self.classname = "item_shells";
|
||||
item_shells();
|
||||
}
|
||||
else if (self.spawnflags & ITW_ROCKETS)
|
||||
{
|
||||
self.spawnflags = self.spawnflags - ITW_ROCKETS;
|
||||
self.classname = "item_rockets";
|
||||
item_rockets();
|
||||
}
|
||||
else if (self.spawnflags & ITW_NAILS)
|
||||
{
|
||||
self.spawnflags = self.spawnflags - ITW_NAILS;
|
||||
self.classname = "item_spikes";
|
||||
item_spikes();
|
||||
}
|
||||
};
|
||||
96
mod_slipgate/source/server/it_armor.qc
Normal file
96
mod_slipgate/source/server/it_armor.qc
Normal file
@@ -0,0 +1,96 @@
|
||||
/*==========
|
||||
armor_touch
|
||||
==========*/
|
||||
static void() armor_touch =
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
if (other.health <= 0)
|
||||
return;
|
||||
// player already has better armor
|
||||
if (other.armortype*other.armorvalue >= self.armortype*self.armorvalue)
|
||||
return;
|
||||
|
||||
sprint(other, "You got the ");
|
||||
sprint(other, self.netname);
|
||||
sprint(other, "\n");
|
||||
|
||||
sound(other, CHAN_ITEM, "items/armor1.wav", 1, ATTN_NORM);
|
||||
stuffcmd (other, "bf\n");
|
||||
|
||||
other.armortype = self.armortype;
|
||||
other.armorvalue = self.armorvalue;
|
||||
other.items = other.items - (other.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)) + self.items;
|
||||
|
||||
self.solid = SOLID_NOT;
|
||||
self.model = string_null;
|
||||
if (deathmatch || self.spawnflags & ITEM_RESPAWN)
|
||||
{
|
||||
self.think = ItemRespawn;
|
||||
self.nextthink = time + self.teleport_time;
|
||||
}
|
||||
|
||||
// fire targets
|
||||
activator = other;
|
||||
UseTargets();
|
||||
};
|
||||
|
||||
/*==========
|
||||
armor_start
|
||||
==========*/
|
||||
static void() armor_start =
|
||||
{
|
||||
SetPositiveDefault(teleport_time, 20);
|
||||
self.touch = armor_touch;
|
||||
precache_model ("progs/armor.mdl");
|
||||
setmodel (self, "progs/armor.mdl");
|
||||
setsize (self, '-16 -16 0', '16 16 56');
|
||||
StartItem ();
|
||||
};
|
||||
|
||||
/*QUAKED item_armor1 (0 0 1) (-16 -16 0) (16 16 56) X X X X DONT_DROP RESPAWN X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path" : "progs/armor.mdl", "skin" : 0});
|
||||
}
|
||||
Green armor. 100 points, saves 30% of damage.
|
||||
*/
|
||||
void() item_armor1 =
|
||||
{
|
||||
self.items = IT_ARMOR1;
|
||||
self.armortype = 0.3;
|
||||
self.armorvalue = 100;
|
||||
self.netname = "Green Armor";
|
||||
armor_start();
|
||||
};
|
||||
|
||||
/*QUAKED item_armor2 (0 0 1) (-16 -16 0) (16 16 56) X X X X DONT_DROP RESPAWN X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path" : "progs/armor.mdl", "skin" : 1});
|
||||
}
|
||||
Yellow armor. 150 points, saves 60% of damage.
|
||||
*/
|
||||
void() item_armor2 =
|
||||
{
|
||||
self.skin = 1;
|
||||
self.items = IT_ARMOR2;
|
||||
self.armortype = 0.6;
|
||||
self.armorvalue = 150;
|
||||
self.netname = "Yellow Armor";
|
||||
armor_start();
|
||||
};
|
||||
|
||||
/*QUAKED item_armorInv (0 0 1) (-16 -16 0) (16 16 56) X X X X DONT_DROP RESPAWN X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path" : "progs/armor.mdl", "skin" : 2});
|
||||
}
|
||||
Red armor. 200 points, saves 80% of damage.
|
||||
*/
|
||||
void() item_armorInv =
|
||||
{
|
||||
self.skin = 2;
|
||||
self.items = IT_ARMOR3;
|
||||
self.armortype = 0.8;
|
||||
self.armorvalue = 200;
|
||||
self.netname = "Red Armor";
|
||||
armor_start();
|
||||
};
|
||||
218
mod_slipgate/source/server/it_backpack.qc
Normal file
218
mod_slipgate/source/server/it_backpack.qc
Normal file
@@ -0,0 +1,218 @@
|
||||
/*==========
|
||||
backpack_touch
|
||||
==========*/
|
||||
void() backpack_touch =
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
if (other.health <= 0)
|
||||
return;
|
||||
|
||||
other.ammo_shells = other.ammo_shells + self.ammo_shells;
|
||||
other.ammo_nails = other.ammo_nails + self.ammo_nails;
|
||||
other.ammo_rockets = other.ammo_rockets + self.ammo_rockets;
|
||||
other.ammo_cells = other.ammo_cells + self.ammo_cells;
|
||||
W_BoundAmmo(other);
|
||||
W_SetCurrentAmmo(other);
|
||||
|
||||
sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
|
||||
stuffcmd (other, "bf\n");
|
||||
|
||||
// tell the player what's inside
|
||||
float comma = FALSE;
|
||||
sprint (other, "You get ");
|
||||
if (self.items)
|
||||
{
|
||||
if (self.items & IT_AXE)
|
||||
{
|
||||
sprint(other, "the Axe");
|
||||
comma = TRUE;
|
||||
}
|
||||
if (self.items & IT_SHOTGUN)
|
||||
{
|
||||
if (comma) sprint(other, ", ");
|
||||
sprint(other, "the Shotgun");
|
||||
comma = TRUE;
|
||||
}
|
||||
if (self.items & IT_SUPER_SHOTGUN)
|
||||
{
|
||||
if (comma) sprint(other, ", ");
|
||||
sprint(other, "the Double-barrelled Shotgun");
|
||||
comma = TRUE;
|
||||
}
|
||||
if (self.items & IT_NAILGUN)
|
||||
{
|
||||
if (comma) sprint(other, ", ");
|
||||
sprint(other, "the Nailgun");
|
||||
comma = TRUE;
|
||||
}
|
||||
if (self.items & IT_SUPER_NAILGUN)
|
||||
{
|
||||
if (comma) sprint(other, ", ");
|
||||
sprint(other, "the Perforator");
|
||||
comma = TRUE;
|
||||
}
|
||||
if (self.items & IT_GRENADE_LAUNCHER)
|
||||
{
|
||||
if (comma) sprint(other, ", ");
|
||||
sprint(other, "the Grenade Launcher");
|
||||
comma = TRUE;
|
||||
}
|
||||
if (self.items & IT_ROCKET_LAUNCHER)
|
||||
{
|
||||
if (comma) sprint(other, ", ");
|
||||
sprint(other, "the Rocket Launcher");
|
||||
comma = TRUE;
|
||||
}
|
||||
if (self.items & IT_LIGHTNING)
|
||||
{
|
||||
if (comma) sprint(other, ", ");
|
||||
sprint(other, "the Thunderbolt");
|
||||
comma = TRUE;
|
||||
}
|
||||
}
|
||||
if (self.ammo_shells)
|
||||
{
|
||||
if (comma) sprint(other, ", ");
|
||||
comma = TRUE;
|
||||
sprint (other, ftos(self.ammo_shells));
|
||||
sprint (other, " shells");
|
||||
}
|
||||
if (self.ammo_nails)
|
||||
{
|
||||
if (comma) sprint(other, ", ");
|
||||
comma = TRUE;
|
||||
sprint (other, ftos(self.ammo_nails));
|
||||
sprint (other, " nails");
|
||||
}
|
||||
if (self.ammo_rockets)
|
||||
{
|
||||
if (comma) sprint(other, ", ");
|
||||
comma = TRUE;
|
||||
sprint (other, ftos(self.ammo_rockets));
|
||||
sprint (other, " rockets");
|
||||
}
|
||||
if (self.ammo_cells)
|
||||
{
|
||||
if (comma) sprint(other, ", ");
|
||||
comma = TRUE;
|
||||
sprint (other, ftos(self.ammo_cells));
|
||||
sprint (other, " cells");
|
||||
}
|
||||
sprint (other, "\n");
|
||||
|
||||
if (self.items)
|
||||
{
|
||||
if (other.items & self.items == 0)
|
||||
{
|
||||
other.items = other.items | self.items;
|
||||
if (!other.weaponframe)
|
||||
{
|
||||
other.weapon = self.items;
|
||||
W_UpdateWeapon(other);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.solid = SOLID_NOT;
|
||||
self.model = string_null;
|
||||
// set up for respawn
|
||||
if (self.classname == "item_backpack" && deathmatch) // map item, not dropped backpack
|
||||
{
|
||||
self.think = ItemRespawn;
|
||||
self.nextthink = time + self.teleport_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.think = SUB_Remove;
|
||||
self.nextthink = time + 0.01;
|
||||
}
|
||||
|
||||
// fire all targets
|
||||
activator = other;
|
||||
UseTargets();
|
||||
};
|
||||
|
||||
/*==========
|
||||
DropBackpack
|
||||
|
||||
called by players and monsters upon death
|
||||
drops a backpack containing current weapon and ammo
|
||||
==========*/
|
||||
void() DropBackpack =
|
||||
{
|
||||
// nothing to drop
|
||||
if (!(self.ammo_shells + self.ammo_nails + self.ammo_rockets + self.ammo_cells))
|
||||
return;
|
||||
|
||||
entity backpack = spawn();
|
||||
backpack.classname = "backpack";
|
||||
|
||||
backpack.items = self.weapon;
|
||||
backpack.ammo_shells = self.ammo_shells;
|
||||
backpack.ammo_nails = self.ammo_nails;
|
||||
backpack.ammo_rockets = self.ammo_rockets;
|
||||
backpack.ammo_cells = self.ammo_cells;
|
||||
|
||||
backpack.flags = FL_ITEM;
|
||||
backpack.solid = SOLID_TRIGGER;
|
||||
backpack.movetype = MOVETYPE_TOSS;
|
||||
setmodel (backpack, "progs/backpack.mdl");
|
||||
setsize (backpack, '-16 -16 0', '16 16 56');
|
||||
setorigin (backpack, self.origin - '0 0 24');
|
||||
backpack.touch = backpack_touch;
|
||||
backpack.velocity = [crandom() * 100, crandom() * 100, 300];
|
||||
|
||||
backpack.nextthink = time + 120;
|
||||
backpack.think = SUB_Remove;
|
||||
};
|
||||
|
||||
/*QUAKED item_backpack (0 0 1) (-16 -16 0) (16 16 56) X X X X DONT_DROP RESPAWN X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{ model("progs/backpack.mdl"); }
|
||||
Backpack pickup. Contains 40 shells, 50 nails, 10 rockets and 12 cells.
|
||||
|
||||
Keys:
|
||||
items - set to one of a combination of the IT_SHOTGUN etc values to make the backpack contain weapons
|
||||
ammo_shells, ammo_nails, ammo_rockets, ammo_cells - set to override ammo defaults. set to -1 to not give ANY ammo of that type.
|
||||
teleport_time - time in seconds to respawn (default 120)
|
||||
|
||||
Spawnflags:
|
||||
DONT_DROP - don't drop to floor on map load
|
||||
RESPAWN - respawn automatically
|
||||
*/
|
||||
void() item_backpack =
|
||||
{
|
||||
precache_model ("progs/backpack.mdl");
|
||||
precache_sound ("weapons/lock4.wav");
|
||||
setmodel (self, "progs/backpack.mdl");
|
||||
setsize (self, '-16 -16 0', '16 16 56');
|
||||
self.touch = backpack_touch;
|
||||
|
||||
SetPositiveDefault(teleport_time, 120);
|
||||
|
||||
// remove anything that isn't a weapon
|
||||
self.items = self.items & (IT_AXE | IT_SHOTGUN | IT_SUPER_SHOTGUN | IT_NAILGUN | IT_SUPER_NAILGUN |
|
||||
IT_GRENADE_LAUNCHER | IT_ROCKET_LAUNCHER | IT_LIGHTNING);
|
||||
|
||||
if (!self.ammo_shells)
|
||||
self.ammo_shells = 40;
|
||||
if (self.ammo_shells < 0)
|
||||
self.ammo_shells = 0;
|
||||
|
||||
if (!self.ammo_nails)
|
||||
self.ammo_nails = 50;
|
||||
if (self.ammo_nails < 0)
|
||||
self.ammo_nails = 0;
|
||||
|
||||
if (!self.ammo_rockets)
|
||||
self.ammo_rockets = 10;
|
||||
if (self.ammo_rockets < 0)
|
||||
self.ammo_rockets = 0;
|
||||
|
||||
if (!self.ammo_cells)
|
||||
self.ammo_cells = 12;
|
||||
if (self.ammo_cells < 0)
|
||||
self.ammo_cells = 0;
|
||||
|
||||
StartItem();
|
||||
};
|
||||
92
mod_slipgate/source/server/it_health.qc
Normal file
92
mod_slipgate/source/server/it_health.qc
Normal file
@@ -0,0 +1,92 @@
|
||||
enumflags { H_ROTTEN, H_MEGA };
|
||||
|
||||
/*==========
|
||||
health_touch
|
||||
==========*/
|
||||
void() health_touch =
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
if (other.health <= 0)
|
||||
return;
|
||||
|
||||
// already at max health?
|
||||
if (other.health >= other.max_health)
|
||||
if (self.health < 100)
|
||||
return;
|
||||
// absolute max health
|
||||
if (other.health >= 250)
|
||||
return;
|
||||
|
||||
// give health and cap it
|
||||
other.health = other.health + self.health;
|
||||
if (other.health > other.max_health)
|
||||
if (self.health < 100)
|
||||
other.health = other.max_health;
|
||||
if (other.health > 250)
|
||||
other.health = 250;
|
||||
|
||||
sprint(other, "You receive ");
|
||||
sprint(other, ftos(self.health));
|
||||
sprint(other, " health\n");
|
||||
|
||||
sound(other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
|
||||
stuffcmd (other, "bf\n");
|
||||
|
||||
if (self.health == 100)
|
||||
{
|
||||
other.items = other.items | IT_SUPERHEALTH;
|
||||
other.health_rot_time = time + 5;
|
||||
}
|
||||
|
||||
self.model = string_null;
|
||||
self.solid = SOLID_NOT;
|
||||
if (deathmatch)
|
||||
{
|
||||
self.think = ItemRespawn;
|
||||
self.nextthink = time + 20;
|
||||
}
|
||||
|
||||
// fire targets
|
||||
activator = other;
|
||||
UseTargets();
|
||||
};
|
||||
|
||||
/*QUAKED item_health (0 0 1) (0 0 0) (32 32 56) Rotten Megahealth X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ( {{ spawnflags & 1 -> { "path" : "maps/b_bh10.bsp" }, spawnflags & 2 -> { "path" : "maps/b_bh100.bsp" },
|
||||
"maps/b_bh25.bsp" }} );
|
||||
}
|
||||
Health box. Normally gives 25 points.
|
||||
Rotten box heals 15 points.
|
||||
Megahealth will add 100 health, then start to
|
||||
rot the player back down to 100 health after 5 seconds.
|
||||
*/
|
||||
void() item_health =
|
||||
{
|
||||
if (self.spawnflags & H_ROTTEN)
|
||||
{
|
||||
precache_model("maps/b_bh10.bsp");
|
||||
setmodel(self, "maps/b_bh10.bsp");
|
||||
self.noise = "items/r_item1.wav";
|
||||
self.health = 15;
|
||||
}
|
||||
else if (self.spawnflags & H_MEGA)
|
||||
{
|
||||
precache_model("maps/b_bh100.bsp");
|
||||
setmodel(self, "maps/b_bh100.bsp");
|
||||
self.noise = "items/r_item2.wav";
|
||||
self.health = 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
precache_model("maps/b_bh25.bsp");
|
||||
setmodel(self, "maps/b_bh25.bsp");
|
||||
self.noise = "items/health1.wav";
|
||||
self.health = 25;
|
||||
}
|
||||
precache_sound(self.noise);
|
||||
self.touch = health_touch;
|
||||
setsize (self, '0 0 0', '32 32 56');
|
||||
StartItem ();
|
||||
};
|
||||
201
mod_slipgate/source/server/it_keys.qc
Normal file
201
mod_slipgate/source/server/it_keys.qc
Normal file
@@ -0,0 +1,201 @@
|
||||
/*========================================
|
||||
it_keys.qc
|
||||
========================================*/
|
||||
|
||||
/*==========
|
||||
key_touch
|
||||
==========*/
|
||||
void() key_touch =
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
if (other.health <= 0)
|
||||
return;
|
||||
if (other.items & self.items)
|
||||
return;
|
||||
|
||||
sprint (other, "You got the ");
|
||||
sprint (other, self.netname);
|
||||
sprint (other,"\n");
|
||||
|
||||
sound (other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
|
||||
stuffcmd (other, "bf\n");
|
||||
other.items = other.items | self.items;
|
||||
|
||||
self.solid = SOLID_NOT;
|
||||
self.model = string_null;
|
||||
|
||||
// fire targets
|
||||
activator = other;
|
||||
UseTargets();
|
||||
};
|
||||
|
||||
/*==========
|
||||
key_setmodel
|
||||
==========*/
|
||||
void() key_setmodel =
|
||||
{
|
||||
if (world.worldtype == 0)
|
||||
{
|
||||
precache_model ("progs/key_med.mdl");
|
||||
setmodel (self, "progs/key_med.mdl");
|
||||
}
|
||||
else if (world.worldtype == 1)
|
||||
{
|
||||
precache_model ("progs/key_rune.mdl");
|
||||
setmodel (self, "progs/key_rune.mdl");
|
||||
}
|
||||
else if (world.worldtype == 2)
|
||||
{
|
||||
precache_model2 ("progs/key_base.mdl");
|
||||
setmodel (self, "progs/key_base.mdl");
|
||||
}
|
||||
};
|
||||
|
||||
/*==========
|
||||
key_setsounds
|
||||
==========*/
|
||||
void() key_setsounds =
|
||||
{
|
||||
if (world.worldtype == 0)
|
||||
self.noise = "misc/medkey.wav";
|
||||
if (world.worldtype == 1)
|
||||
self.noise = "misc/runekey.wav";
|
||||
if (world.worldtype == 2)
|
||||
self.noise = "misc/basekey.wav";
|
||||
precache_sound(self.noise);
|
||||
};
|
||||
|
||||
/*QUAKED item_key1 (0 0 1) (-16 -16 -24) (16 16 32) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{ model("progs/key_med.mdl"); }
|
||||
SILVER key
|
||||
In order for keys to work
|
||||
you MUST set your maps
|
||||
worldtype to one of the
|
||||
following:
|
||||
0: medieval
|
||||
1: metal
|
||||
2: base
|
||||
*/
|
||||
void() item_key1 =
|
||||
{
|
||||
if (world.worldtype == 0)
|
||||
self.netname = "silver key";
|
||||
else if (world.worldtype == 1)
|
||||
self.netname = "silver runekey";
|
||||
else if (world.worldtype == 2)
|
||||
self.netname = "silver keycard";
|
||||
key_setmodel();
|
||||
key_setsounds();
|
||||
self.touch = key_touch;
|
||||
self.items = IT_KEY1;
|
||||
setsize (self, '-16 -16 -24', '16 16 32');
|
||||
StartItem ();
|
||||
};
|
||||
|
||||
/*QUAKED item_key2 (0 0 1) (-16 -16 -24) (16 16 32) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path" : "progs/key_med.mdl", "skin" : 1});
|
||||
}
|
||||
GOLD key
|
||||
In order for keys to work
|
||||
you MUST set your maps
|
||||
worldtype to one of the
|
||||
following:
|
||||
0: medieval
|
||||
1: metal
|
||||
2: base
|
||||
*/
|
||||
void() item_key2 =
|
||||
{
|
||||
if (world.worldtype == 0)
|
||||
self.netname = "gold key";
|
||||
else if (world.worldtype == 1)
|
||||
self.netname = "gold runekey";
|
||||
else if (world.worldtype == 2)
|
||||
self.netname = "gold keycard";
|
||||
key_setmodel();
|
||||
key_setsounds();
|
||||
self.skin = 1;
|
||||
self.touch = key_touch;
|
||||
self.items = IT_KEY2;
|
||||
setsize (self, '-16 -16 -24', '16 16 32');
|
||||
StartItem ();
|
||||
};
|
||||
|
||||
/*==========
|
||||
sigil_touch
|
||||
==========*/
|
||||
void() sigil_touch =
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
if (other.health <= 0)
|
||||
return;
|
||||
|
||||
serverflags = serverflags | (self.spawnflags & 15);
|
||||
centerprint (other, "You got the Rune of ", self.netname, " Magic!");
|
||||
sound (other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
|
||||
stuffcmd (other, "bf\n");
|
||||
|
||||
self.solid = SOLID_NOT;
|
||||
self.model = string_null;
|
||||
|
||||
// fire targets
|
||||
activator = other;
|
||||
UseTargets();
|
||||
};
|
||||
|
||||
/*QUAKED item_sigil (0 0 1) (-16 -16 -24) (16 16 32) E1 E2 E3 E4 X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ( {{ spawnflags & 1 -> { "path" : "progs/end1.mdl" }, spawnflags & 2 -> { "path" : "progs/end2.mdl" },
|
||||
spawnflags & 4 -> { "path" : "progs/end3.mdl" }, spawnflags & 8 -> { "path" : "progs/end4.mdl" },
|
||||
"progs/end1.mdl" }} );
|
||||
}
|
||||
End of episode rune. Use in conjuction with func_bossgate and func_episodegate.
|
||||
Spawnflag must be set to the appropriate episode.
|
||||
Episode 1 - Dimension of the Doomed - Rune of Earth Magic
|
||||
Episode 2 - The Realm of Black Magic - Rune of Black Magic
|
||||
Episode 3 - The Netherworld - Rune of Hell Magic
|
||||
Episode 4 - The Elder World - Run of Elder Magic
|
||||
*/
|
||||
void() item_sigil =
|
||||
{
|
||||
self.noise = "misc/runekey.wav";
|
||||
precache_sound(self.noise);
|
||||
|
||||
if (self.spawnflags & 1)
|
||||
{
|
||||
self.netname = "Earth";
|
||||
precache_model ("progs/end1.mdl");
|
||||
setmodel (self, "progs/end1.mdl");
|
||||
}
|
||||
else if (self.spawnflags & 2)
|
||||
{
|
||||
self.netname = "Black";
|
||||
precache_model2 ("progs/end2.mdl");
|
||||
setmodel (self, "progs/end2.mdl");
|
||||
}
|
||||
else if (self.spawnflags & 4)
|
||||
{
|
||||
self.netname = "Hell";
|
||||
precache_model2 ("progs/end3.mdl");
|
||||
setmodel (self, "progs/end3.mdl");
|
||||
}
|
||||
else if (self.spawnflags & 8)
|
||||
{
|
||||
self.netname = "Elder";
|
||||
precache_model2 ("progs/end4.mdl");
|
||||
setmodel (self, "progs/end4.mdl");
|
||||
}
|
||||
else
|
||||
{
|
||||
objerror("invalid spawnflags\n");
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
|
||||
self.touch = sigil_touch;
|
||||
setsize (self, '-16 -16 -24', '16 16 32');
|
||||
StartItem ();
|
||||
};
|
||||
109
mod_slipgate/source/server/it_powerups.qc
Normal file
109
mod_slipgate/source/server/it_powerups.qc
Normal file
@@ -0,0 +1,109 @@
|
||||
/*==========
|
||||
powerup_touch
|
||||
==========*/
|
||||
void() powerup_touch =
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
if (other.health <= 0)
|
||||
return;
|
||||
|
||||
sprint (other, "You got the ");
|
||||
sprint (other, self.netname);
|
||||
sprint (other,"\n");
|
||||
|
||||
sound (other, CHAN_VOICE, self.noise, 1, ATTN_NORM);
|
||||
stuffcmd (other, "bf\n");
|
||||
|
||||
self.model = string_null;
|
||||
self.solid = SOLID_NOT;
|
||||
other.items = other.items | self.items;
|
||||
|
||||
if (self.classname == "item_artifact_envirosuit")
|
||||
{
|
||||
other.rad_time = 1;
|
||||
other.radsuit_finished = time + 30;
|
||||
}
|
||||
if (self.classname == "item_artifact_invulnerability")
|
||||
{
|
||||
other.invincible_time = 1;
|
||||
other.invincible_finished = time + 30;
|
||||
}
|
||||
if (self.classname == "item_artifact_invisibility")
|
||||
{
|
||||
other.invisible_time = 1;
|
||||
other.invisible_finished = time + 30;
|
||||
}
|
||||
if (self.classname == "item_artifact_super_damage")
|
||||
{
|
||||
other.super_time = 1;
|
||||
other.super_damage_finished = time + 30;
|
||||
}
|
||||
|
||||
if (deathmatch || self.spawnflags & ITEM_RESPAWN)
|
||||
{
|
||||
self.think = ItemRespawn;
|
||||
self.nextthink = time + self.teleport_time;
|
||||
}
|
||||
|
||||
// fire targets
|
||||
activator = other;
|
||||
UseTargets();
|
||||
};
|
||||
|
||||
/*===========
|
||||
powerup_start
|
||||
==========*/
|
||||
static void(string mod, string snd, string name, float it, float respawn) powerup_start =
|
||||
{
|
||||
precache_model (mod);
|
||||
setmodel (self, mod);
|
||||
precache_sound (snd);
|
||||
self.noise = snd;
|
||||
SetPositiveDefault(teleport_time, respawn);
|
||||
self.netname = name;
|
||||
self.items = it;
|
||||
setsize (self, '-16 -16 -24', '16 16 32');
|
||||
self.touch = powerup_touch;
|
||||
StartItem();
|
||||
};
|
||||
|
||||
/*QUAKED item_artifact_invulnerability (0 0 1) (-16 -16 -24) (16 16 32) X X X X DONT_DROP RESPAWN X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{ model("progs/invulner.mdl"); }
|
||||
Pentagram of Protection
|
||||
Player is invulnerable for 30 seconds
|
||||
*/
|
||||
void() item_artifact_invulnerability =
|
||||
{
|
||||
powerup_start("progs/invulner.mdl", "items/protect.wav", "Pentagram of Protection", IT_INVULNERABILITY, 300);
|
||||
};
|
||||
|
||||
/*QUAKED item_artifact_envirosuit (0 0 1) (-16 -16 -24) (16 16 32) X X X X DONT_DROP RESPAWN X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{ model("progs/suit.mdl"); }
|
||||
Biosuit
|
||||
Player takes no damage from water or slime for 30 seconds
|
||||
*/
|
||||
void() item_artifact_envirosuit =
|
||||
{
|
||||
powerup_start("progs/suit.mdl", "items/suit.wav", "Biosuit", IT_SUIT, 60);
|
||||
};
|
||||
|
||||
/*QUAKED item_artifact_invisibility (0 0 1) (-16 -16 -24) (16 16 32) X X X X DONT_DROP RESPAWN X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{ model("progs/invisibl.mdl"); }
|
||||
Ring of Shadows
|
||||
Player is invisible for 30 seconds
|
||||
*/
|
||||
void() item_artifact_invisibility =
|
||||
{
|
||||
powerup_start("progs/invisibl.mdl", "items/inv1.wav", "Ring of Shadows", IT_INVISIBILITY, 300);
|
||||
};
|
||||
|
||||
/*QUAKED item_artifact_super_damage (0 0 1) (-16 -16 -24) (16 16 32) X X X X DONT_DROP RESPAWN X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{ model("progs/quaddama.mdl"); }
|
||||
Quad Damage
|
||||
Player does 4x damage for 30 seconds
|
||||
*/
|
||||
void() item_artifact_super_damage =
|
||||
{
|
||||
powerup_start("progs/quaddama.mdl", "items/damage.wav", "Quad Damage", IT_QUAD, 60);
|
||||
};
|
||||
153
mod_slipgate/source/server/it_weapons.qc
Normal file
153
mod_slipgate/source/server/it_weapons.qc
Normal file
@@ -0,0 +1,153 @@
|
||||
/*==========
|
||||
weapon_touch
|
||||
==========*/
|
||||
static void() weapon_touch =
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
if (other.health <= 0)
|
||||
return;
|
||||
if (coop && (other.items & self.weapon))
|
||||
{
|
||||
// fire targets in coop even if all players already have the weapon
|
||||
if (!self.count)
|
||||
{
|
||||
activator = other;
|
||||
UseTargets();
|
||||
}
|
||||
self.count = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
other.ammo_shells = other.ammo_shells + self.ammo_shells;
|
||||
other.ammo_nails = other.ammo_nails + self.ammo_nails;
|
||||
other.ammo_rockets = other.ammo_rockets + self.ammo_rockets;
|
||||
other.ammo_cells = other.ammo_cells + self.ammo_cells;
|
||||
W_BoundAmmo(other);
|
||||
W_SetCurrentAmmo(other);
|
||||
|
||||
sprint (other, "You got the ");
|
||||
sprint (other, self.netname);
|
||||
sprint (other, "\n");
|
||||
|
||||
sound (other, CHAN_ITEM, "weapons/pkup.wav", 1, ATTN_NORM);
|
||||
stuffcmd (other, "bf\n");
|
||||
|
||||
self.model = string_null;
|
||||
self.solid = SOLID_NOT;
|
||||
if (deathmatch)
|
||||
{
|
||||
self.think = ItemRespawn;
|
||||
self.nextthink = time + 30;
|
||||
}
|
||||
|
||||
if (!(other.items & self.weapon))
|
||||
{
|
||||
other.items = other.items | self.weapon;
|
||||
if (!other.weaponframe)
|
||||
{
|
||||
other.weapon = self.weapon;
|
||||
W_UpdateWeapon(other);
|
||||
}
|
||||
}
|
||||
|
||||
// fire targets
|
||||
activator = other;
|
||||
UseTargets();
|
||||
};
|
||||
|
||||
/*QUAKED weapon_supershotgun (0 0 1) (-16 -16 0) (16 16 56) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{ model("progs/g_shot.mdl"); }
|
||||
Double-barrelled Shotgun
|
||||
*/
|
||||
void() weapon_supershotgun =
|
||||
{
|
||||
precache_model ("progs/g_shot.mdl");
|
||||
setmodel (self, "progs/g_shot.mdl");
|
||||
self.weapon = IT_SUPER_SHOTGUN;
|
||||
self.netname = "Double-barrelled Shotgun";
|
||||
self.ammo_shells = 5;
|
||||
self.touch = weapon_touch;
|
||||
setsize (self, '-16 -16 0', '16 16 56');
|
||||
StartItem ();
|
||||
};
|
||||
|
||||
/*QUAKED weapon_nailgun (0 0 1) (-16 -16 0) (16 16 56) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{ model("progs/g_nail.mdl"); }
|
||||
Nailgun
|
||||
*/
|
||||
void() weapon_nailgun =
|
||||
{
|
||||
precache_model ("progs/g_nail.mdl");
|
||||
setmodel (self, "progs/g_nail.mdl");
|
||||
self.weapon = IT_NAILGUN;
|
||||
self.netname = "nailgun";
|
||||
self.ammo_nails = 30;
|
||||
self.touch = weapon_touch;
|
||||
setsize (self, '-16 -16 0', '16 16 56');
|
||||
StartItem ();
|
||||
};
|
||||
|
||||
/*QUAKED weapon_supernailgun (0 0 1) (-16 -16 0) (16 16 56) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{ model("progs/g_nail2.mdl"); }
|
||||
Perforator
|
||||
*/
|
||||
void() weapon_supernailgun =
|
||||
{
|
||||
precache_model ("progs/g_nail2.mdl");
|
||||
setmodel (self, "progs/g_nail2.mdl");
|
||||
self.weapon = IT_SUPER_NAILGUN;
|
||||
self.netname = "Super Nailgun";
|
||||
self.ammo_nails = 30;
|
||||
self.touch = weapon_touch;
|
||||
setsize (self, '-16 -16 0', '16 16 56');
|
||||
StartItem ();
|
||||
};
|
||||
|
||||
/*QUAKED weapon_grenadelauncher (0 0 1) (-16 -16 0) (16 16 56) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{ model("progs/g_rock.mdl"); }
|
||||
Grenade Launcher
|
||||
*/
|
||||
void() weapon_grenadelauncher =
|
||||
{
|
||||
precache_model ("progs/g_rock.mdl");
|
||||
setmodel (self, "progs/g_rock.mdl");
|
||||
self.weapon = IT_GRENADE_LAUNCHER;
|
||||
self.netname = "Grenade Launcher";
|
||||
self.ammo_rockets = 5;
|
||||
self.touch = weapon_touch;
|
||||
setsize (self, '-16 -16 0', '16 16 56');
|
||||
StartItem ();
|
||||
};
|
||||
|
||||
/*QUAKED weapon_rocketlauncher (0 0 1) (-16 -16 0) (16 16 56) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{ model("progs/g_rock2.mdl"); }
|
||||
Rocket Launcher
|
||||
*/
|
||||
void() weapon_rocketlauncher =
|
||||
{
|
||||
precache_model ("progs/g_rock2.mdl");
|
||||
setmodel (self, "progs/g_rock2.mdl");
|
||||
self.weapon = IT_ROCKET_LAUNCHER;
|
||||
self.netname = "Rocket Launcher";
|
||||
self.ammo_rockets = 5;
|
||||
self.touch = weapon_touch;
|
||||
setsize (self, '-16 -16 0', '16 16 56');
|
||||
StartItem ();
|
||||
};
|
||||
|
||||
/*QUAKED weapon_lightning (0 0 1) (-16 -16 0) (16 16 56) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{ model("progs/g_light.mdl"); }
|
||||
Thunderbolt
|
||||
*/
|
||||
void() weapon_lightning =
|
||||
{
|
||||
precache_model ("progs/g_light.mdl");
|
||||
setmodel (self, "progs/g_light.mdl");
|
||||
self.weapon = IT_LIGHTNING;
|
||||
self.netname = "Thunderbolt";
|
||||
self.ammo_cells = 15;
|
||||
self.touch = weapon_touch;
|
||||
setsize (self, '-16 -16 0', '16 16 56');
|
||||
StartItem();
|
||||
};
|
||||
59
mod_slipgate/source/server/items.qc
Normal file
59
mod_slipgate/source/server/items.qc
Normal file
@@ -0,0 +1,59 @@
|
||||
enumflags { ITEM_DONT_DROP=16, ITEM_RESPAWN };
|
||||
|
||||
/*==========
|
||||
ItemRespawn
|
||||
==========*/
|
||||
void() ItemRespawn =
|
||||
{
|
||||
sound (self, CHAN_VOICE, "items/itembk2.wav", 1, ATTN_NORM);
|
||||
self.model = self.mdl;
|
||||
self.solid = SOLID_TRIGGER;
|
||||
setorigin (self, self.origin); // link back into world
|
||||
};
|
||||
|
||||
/*==========
|
||||
PlaceItem
|
||||
==========*/
|
||||
void() PlaceItem =
|
||||
{
|
||||
self.mdl = self.model;
|
||||
self.flags = FL_ITEM;
|
||||
self.solid = SOLID_TRIGGER;
|
||||
|
||||
if (self.spawnflags & ITEM_DONT_DROP)
|
||||
{
|
||||
self.movetype = MOVETYPE_NONE;
|
||||
setorigin(self, self.origin);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.movetype = MOVETYPE_TOSS;
|
||||
setorigin(self, self.origin + '0 0 6');
|
||||
if (!droptofloor())
|
||||
{
|
||||
dprint(self.classname);
|
||||
dprint (" fell out of level at ");
|
||||
dprint (vtos(self.origin));
|
||||
dprint ("\n");
|
||||
remove(self);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*==========
|
||||
StartItem
|
||||
==========*/
|
||||
void() StartItem =
|
||||
{
|
||||
if (self.spawnflags & (ITEM_DONT_DROP | ITEM_RESPAWN))
|
||||
{
|
||||
dprint("potential ");
|
||||
dprint(self.classname);
|
||||
dprint(" with erroneous spawnflag at ");
|
||||
dprint(vtos(self.origin));
|
||||
dprint("\n");
|
||||
}
|
||||
|
||||
self.think = PlaceItem;
|
||||
self.nextthink = time + 0.2;
|
||||
};
|
||||
373
mod_slipgate/source/server/lights.qc
Normal file
373
mod_slipgate/source/server/lights.qc
Normal file
@@ -0,0 +1,373 @@
|
||||
/*========================================
|
||||
lights.qc
|
||||
========================================*/
|
||||
|
||||
static enumflags { LIGHT_START_OFF, LIGHT_FADE, LIGHT_NO_SOUND };
|
||||
|
||||
#define FADE_RAMP 13
|
||||
static string abc[FADE_RAMP] = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m" };
|
||||
|
||||
#define NUM_LIGHTSTYLES 13
|
||||
static string lightstyles[NUM_LIGHTSTYLES] =
|
||||
{
|
||||
// 0 NORMAL
|
||||
"m",
|
||||
// 1 FLICKER (first variety)
|
||||
"mmnmmommommnonmmonqnmmo",
|
||||
// 2 SLOW STRONG PULSE
|
||||
"abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba",
|
||||
// 3 CANDLE (first variety)
|
||||
"mmmmmaaaaammmmmaaaaaabcdefgabcdefg",
|
||||
// 4 FAST STROBE
|
||||
"mamamamamama",
|
||||
// 5 GENTLE PULSE 1
|
||||
"jklmnopqrstuvwxyzyxwvutsrqponmlkj",
|
||||
// 6 FLICKER (second variety)
|
||||
"nmonqnmomnmomomno",
|
||||
// 7 CANDLE (second variety)
|
||||
"mmmaaaabcdefgmmmmaaaammmaamm",
|
||||
// 8 CANDLE (third variety)
|
||||
"mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa",
|
||||
// 9 SLOW STROBE (fourth variety)
|
||||
"aaaaaaaazzzzzzzz",
|
||||
// 10 FLUORESCENT FLICKER
|
||||
"mmamammmmammamamaaamammma",
|
||||
// 11 SLOW PULSE NOT FADE TO BLACK
|
||||
"abcdefghijklmnopqrrqponmlkjihgfedcba",
|
||||
// 12 BLINK OFF / ON (can be combined with animated textures, e.g. +0light, +1light, +alight)
|
||||
"aamm"
|
||||
};
|
||||
|
||||
/*==========
|
||||
lightstyle_lookup
|
||||
|
||||
look up a style by it's number and return the correct animation string
|
||||
==========*/
|
||||
static string(float num) lightstyle_lookup =
|
||||
{
|
||||
if (num > NUM_LIGHTSTYLES - 1)
|
||||
num = NUM_LIGHTSTYLES - 1;
|
||||
if (num < 0)
|
||||
num = 0;
|
||||
return lightstyles[num];
|
||||
};
|
||||
|
||||
/*==========
|
||||
lightstyle_fade_lookup
|
||||
==========*/
|
||||
static string(float num) lightstyle_fade_lookup =
|
||||
{
|
||||
if (num > FADE_RAMP - 1)
|
||||
num = FADE_RAMP - 1;
|
||||
if (num < 0)
|
||||
num = 0;
|
||||
return abc[num];
|
||||
};
|
||||
|
||||
/*==========
|
||||
setup_lightstyles
|
||||
|
||||
Setup light animation tables. 'a' is total darkness, 'z' is maxbright.
|
||||
Styles 32+ are assigned by the light compiler for switchable lights.
|
||||
==========*/
|
||||
void() setup_lightstyles =
|
||||
{
|
||||
for (float i = 0; i < NUM_LIGHTSTYLES - 1; i++)
|
||||
{
|
||||
lightstyle(i, lightstyle_lookup(i));
|
||||
}
|
||||
};
|
||||
|
||||
/*==========
|
||||
light_fade_in
|
||||
==========*/
|
||||
static void() light_fade_in =
|
||||
{
|
||||
lightstyle(self.style, lightstyle_fade_lookup(self.count));
|
||||
|
||||
self.count = self.count + 1;
|
||||
if (self.count > FADE_RAMP - 1)
|
||||
{
|
||||
self.count = FADE_RAMP - 1;
|
||||
return;
|
||||
}
|
||||
|
||||
self.think = light_fade_in;
|
||||
self.nextthink = time + self.speed;
|
||||
};
|
||||
|
||||
/*==========
|
||||
light_fade_out
|
||||
==========*/
|
||||
static void() light_fade_out =
|
||||
{
|
||||
lightstyle(self.style, lightstyle_fade_lookup(self.count));
|
||||
|
||||
self.count = self.count - 1;
|
||||
if (self.count < 0)
|
||||
{
|
||||
self.count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
self.think = light_fade_out;
|
||||
self.nextthink = time + self.speed;
|
||||
};
|
||||
|
||||
/*==========
|
||||
light_use
|
||||
|
||||
using a light will turn it on and off
|
||||
==========*/
|
||||
static void() light_use =
|
||||
{
|
||||
if (self.spawnflags & LIGHT_START_OFF)
|
||||
{
|
||||
if (self.mdl != "")
|
||||
setmodel(self, self.mdl);
|
||||
if (self.noise1 != "")
|
||||
sound(self, CHAN_VOICE, self.noise2, 0.5, ATTN_IDLE);
|
||||
|
||||
self.spawnflags = self.spawnflags - LIGHT_START_OFF;
|
||||
if (self.spawnflags & LIGHT_FADE && !self.style2)
|
||||
light_fade_in();
|
||||
else
|
||||
lightstyle(self.style, lightstyle_lookup(self.style2));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self.mdl != "")
|
||||
self.modelindex = 0;
|
||||
if (self.noise1 != "")
|
||||
sound(self, CHAN_VOICE, self.noise1, 0.5, ATTN_IDLE);
|
||||
|
||||
self.spawnflags = self.spawnflags + LIGHT_START_OFF;
|
||||
if (self.spawnflags & LIGHT_FADE && !self.style2)
|
||||
light_fade_out();
|
||||
else
|
||||
lightstyle(self.style, "a");
|
||||
}
|
||||
};
|
||||
|
||||
/*QUAKED light (1 1 0) (-8 -8 -8) (8 8 8) START_OFF FADE NO_SOUND
|
||||
Non-displayed light
|
||||
Please see your compiling utility documentation for full details,
|
||||
this entry only describes things controlled by the QuakeC.
|
||||
|
||||
==========
|
||||
Keys
|
||||
==========
|
||||
"targetname" "name"
|
||||
Turns the light into a switchable light. You must target it to toggle it.
|
||||
|
||||
"speed" "n"
|
||||
If the light is switchable and FADE_IN_OUT is set, the speed at which the light transitions from off to on and vice versa. Default 0.1.
|
||||
|
||||
"style" "n"
|
||||
Set the animated light style. Default 0.
|
||||
0 NORMAL
|
||||
1 FLICKER (first variety)
|
||||
2 SLOW STRONG PULSE
|
||||
3 CANDLE (first variety)
|
||||
4 FAST STROBE
|
||||
5 GENTLE PULSE 1
|
||||
6 FLICKER (second variety)
|
||||
7 CANDLE (second variety)
|
||||
8 CANDLE (third variety)
|
||||
9 SLOW STROBE (fourth variety)
|
||||
10 FLUORESCENT FLICKER
|
||||
11 SLOW PULSE NOT FADE TO BLACK
|
||||
12 BLINK OFF / ON (can be synced with animated textures, e.g. +0light, +1light, +alight)
|
||||
|
||||
"style2" "n"
|
||||
Set the animated light style for a switchable light.
|
||||
This is because "style" will be set by your compiling utility to a value in the range 32+,
|
||||
so we need to tell the QuakeC what actual style to use.
|
||||
|
||||
==========
|
||||
Spawnflags
|
||||
==========
|
||||
START_OFF - switchable lights only - light is switched off at map start - default is on
|
||||
FADE - switchable lights only - light fades in and out when switched. you can't combine this with an animated style.
|
||||
*/
|
||||
static void() light =
|
||||
{
|
||||
if (self.mdl != "")
|
||||
{
|
||||
if (!(self.spawnflags & LIGHT_START_OFF))
|
||||
setmodel(self, self.mdl);
|
||||
}
|
||||
|
||||
// non-switchable light
|
||||
if (!self.targetname)
|
||||
{
|
||||
//remove(self);
|
||||
return;
|
||||
}
|
||||
|
||||
// default fade speed
|
||||
if (self.speed <= 0)
|
||||
self.speed = 0.1;
|
||||
|
||||
// switchable light
|
||||
if (self.style >= 32)
|
||||
{
|
||||
self.use = light_use;
|
||||
if (self.spawnflags & LIGHT_START_OFF)
|
||||
{
|
||||
self.count = 0;
|
||||
lightstyle(self.style, "a");
|
||||
}
|
||||
else
|
||||
{
|
||||
self.count = FADE_RAMP - 1;
|
||||
lightstyle(self.style, lightstyle_lookup(self.style2));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*QUAKED light_fluoro (1 1 0) (-8 -8 -8) (8 8 8) START_OFF FADE NO_SOUND
|
||||
Non-displayed light
|
||||
Makes steady fluorescent humming sound
|
||||
*/
|
||||
static void() light_fluoro =
|
||||
{
|
||||
ambient_light_buzz();
|
||||
remove(self);
|
||||
};
|
||||
|
||||
/*QUAKED light_fluorospark (1 1 0) (-8 -8 -8) (8 8 8) START_OFF FADE NO_SOUND
|
||||
Non-displayed light
|
||||
Makes sparking, broken fluorescent sound
|
||||
*/
|
||||
static void() light_fluorospark =
|
||||
{
|
||||
ambient_flouro_buzz();
|
||||
remove(self);
|
||||
};
|
||||
|
||||
/*QUAKED light_globe (1 1 0) (-8 -8 -8) (8 8 8) START_OFF FADE NO_SOUND
|
||||
Sprite globe light
|
||||
*/
|
||||
static void() light_globe =
|
||||
{
|
||||
precache_model("progs/s_light.spr");
|
||||
setmodel(self, "progs/s_light.spr");
|
||||
makestatic(self);
|
||||
};
|
||||
|
||||
/*QUAKED light_torch_small_walltorch (1 1 0) (-4 -4 -16) (4 4 32) START_OFF FADE NO_SOUND
|
||||
{ model ("progs/flame.mdl"); }
|
||||
Short wall torch
|
||||
Makes crackling fire noise unless NO_SOUND is set
|
||||
*/
|
||||
static void() light_torch_small_walltorch =
|
||||
{
|
||||
precache_model("progs/flame.mdl");
|
||||
setmodel(self, "progs/flame.mdl");
|
||||
if (!(self.spawnflags & LIGHT_NO_SOUND))
|
||||
ambient_fire();
|
||||
makestatic(self);
|
||||
};
|
||||
|
||||
/*QUAKED light_torch_long_walltorch (1 1 0) (-8 -8 -48) (8 8 24) START_OFF FADE NO_SOUND
|
||||
{ model ("progs/flame3.mdl"); }
|
||||
Long wall torch
|
||||
Makes crackling fire noise unless NO_SOUND is set
|
||||
*/
|
||||
static void() light_torch_long_walltorch =
|
||||
{
|
||||
precache_model("progs/flame3.mdl");
|
||||
setmodel(self, "progs/flame3.mdl");
|
||||
if (!(self.spawnflags & LIGHT_NO_SOUND))
|
||||
ambient_fire();
|
||||
makestatic(self);
|
||||
};
|
||||
|
||||
/*QUAKED light_flame_small_yellow (1 1 0) (-4 -4 -12) (4 4 16) START_OFF FADE NO_SOUND
|
||||
{ model ("progs/flame2.mdl"); }
|
||||
Small yellow flame
|
||||
Makes crackling fire noise unless NO_SOUND is set
|
||||
*/
|
||||
static void() light_flame_small_yellow =
|
||||
{
|
||||
precache_model("progs/flame2.mdl");
|
||||
setmodel(self, "progs/flame2.mdl");
|
||||
if (!(self.spawnflags & LIGHT_NO_SOUND))
|
||||
ambient_fire();
|
||||
makestatic(self);
|
||||
};
|
||||
|
||||
/*==========
|
||||
light_flame_small_white
|
||||
For compatability only.
|
||||
==========*/
|
||||
static void() light_flame_small_white =
|
||||
{
|
||||
self.classname = "light_flame_small_yellow";
|
||||
light_flame_small_yellow();
|
||||
};
|
||||
|
||||
/*QUAKED light_flame_large_yellow (1 1 0) (-8 -8 -12) (8 8 40) START_OFF FADE NO_SOUND
|
||||
{ model ( { "path" : "progs/flame2.mdl", "frame" : 1 } ); }
|
||||
Large yellow flame
|
||||
Makes crackling fire noise unless NO_SOUND is set
|
||||
*/
|
||||
static void() light_flame_large_yellow =
|
||||
{
|
||||
precache_model("progs/flame2.mdl");
|
||||
setmodel (self, "progs/flame2.mdl");
|
||||
self.frame = 1;
|
||||
if (!(self.spawnflags & LIGHT_NO_SOUND))
|
||||
ambient_fire();
|
||||
makestatic(self);
|
||||
};
|
||||
|
||||
/*==========
|
||||
s_flame
|
||||
==========*/
|
||||
static void() s_flame =
|
||||
{
|
||||
self.frame = self.frame + 1;
|
||||
if (self.frame > 13)
|
||||
self.frame = 0;
|
||||
self.think = s_flame;
|
||||
self.nextthink = time + 0.05;
|
||||
};
|
||||
|
||||
/*QUAKED light_flame_sprite (1 1 0) (-16 -16 0) (16 16 40) START_OFF FADE NO_SOUND
|
||||
Large yellow flame sprite
|
||||
Makes crackling fire noise
|
||||
See the "light" entity for a full description
|
||||
*/
|
||||
static void() light_flame_sprite =
|
||||
{
|
||||
self.mdl = "progs/s_flame.spr";
|
||||
precache_model(self.mdl);
|
||||
|
||||
self.noise = "ambience/fire1.wav";
|
||||
precache_sound(self.noise);
|
||||
self.noise1 = "misc/torchoff.wav";
|
||||
precache_sound(self.noise1);
|
||||
self.noise2 = "misc/torchon1.wav";
|
||||
precache_sound(self.noise2);
|
||||
|
||||
if (!(self.spawnflags & LIGHT_NO_SOUND))
|
||||
ambient_fire();
|
||||
|
||||
light();
|
||||
|
||||
// assume any sensible engine that implements pr_checkextension
|
||||
// also has working spritegroups, so we can use
|
||||
// makestatic and reduce network traffic
|
||||
if (cvar("pr_checkextension"))
|
||||
{
|
||||
self.frame = 14; // frame 14 is a spritegroup which contains 14 frames
|
||||
//makestatic(self);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.think = s_flame; // animate frames 0-13 manually
|
||||
self.nextthink = time + 0.01 + random() * 0.5;
|
||||
}
|
||||
};
|
||||
466
mod_slipgate/source/server/misc.qc
Normal file
466
mod_slipgate/source/server/misc.qc
Normal file
@@ -0,0 +1,466 @@
|
||||
enumflags { MISC_MODEL_SOLID };
|
||||
|
||||
/*QUAKED misc_model (0 0 1) (-16 -16 -16) (16 16 16) SOLID X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path" : mdl, "skin" : skin, "frame": frame});
|
||||
}
|
||||
Custom map object. Non-solid by default.
|
||||
|
||||
Keys:
|
||||
"mdl" "name" - model to load, e.g. "progs/grenade.mdl"
|
||||
"pos1", "pos2" "vector" - bounding box size. if not defined it will default to '-16 -16 -16', '16 16 16'
|
||||
"skin" "n" - model or sprite skin
|
||||
"frame" "n" - model or sprite frame
|
||||
|
||||
Spawnflags:
|
||||
SOLID - Model is solid
|
||||
*/
|
||||
void() misc_model =
|
||||
{
|
||||
if (!self.mdl)
|
||||
{
|
||||
objerror("no mdl");
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
precache_model(self.mdl);
|
||||
|
||||
self.movetype = MOVETYPE_NONE;
|
||||
if (self.spawnflags & MISC_MODEL_SOLID)
|
||||
self.solid = SOLID_BBOX;
|
||||
else
|
||||
self.solid = SOLID_NOT;
|
||||
|
||||
setmodel(self, self.mdl);
|
||||
if (self.pos1 && self.pos2)
|
||||
setsize(self, self.pos1, self.pos2);
|
||||
else
|
||||
setsize(self, '-16 -16 -16', '16 16 16');
|
||||
|
||||
if (!(self.spawnflags & MISC_MODEL_SOLID))
|
||||
makestatic(self);
|
||||
};
|
||||
|
||||
/*QUAKED misc_demon_dead (1 0 0) (-32 -32 -24) (32 32 0) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path":"progs/demon.mdl","frame":53});
|
||||
}
|
||||
Dead Fiend
|
||||
*/
|
||||
void() misc_demon_dead =
|
||||
{
|
||||
self.mdl = "progs/demon.mdl";
|
||||
self.pos1 = '-32 -32 -24';
|
||||
self.pos2 = '32 32 0';
|
||||
self.frame = 53;
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_demon_head (1 0 0) (-16 -16 0) (16 16 16) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ("progs/h_demon.mdl");
|
||||
}
|
||||
Fiend Head
|
||||
*/
|
||||
void() misc_demon_head =
|
||||
{
|
||||
self.mdl = "progs/h_demon.mdl";
|
||||
self.pos1 = '-16 -16 0';
|
||||
self.pos2 = '16 16 16';
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_dog_dead_1 (1 0 0) (-16 -16 -24) (16 16 0) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path":"progs/dog.mdl","frame":16});
|
||||
}
|
||||
Dead dog
|
||||
*/
|
||||
void() misc_dog_dead_1 =
|
||||
{
|
||||
self.mdl = "progs/dog.mdl";
|
||||
self.pos1 = '-16 -16 -24';
|
||||
self.pos2 = '16 16 0';
|
||||
self.frame = 16;
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_dog_dead_2 (1 0 0) (-16 -16 -24) (16 16 0) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path":"progs/dog.mdl","frame":25});
|
||||
}
|
||||
Dead dog
|
||||
*/
|
||||
void() misc_dog_dead_2 =
|
||||
{
|
||||
self.mdl = "progs/dog.mdl";
|
||||
self.pos1 = '-16 -16 -24';
|
||||
self.pos2 = '16 16 0';
|
||||
self.frame = 25;
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_dog_head (1 0 0) (-16 -16 0) (16 16 16) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ("progs/h_dog.mdl");
|
||||
}
|
||||
dog Head
|
||||
*/
|
||||
void() misc_dog_head =
|
||||
{
|
||||
self.mdl = "progs/h_dog.mdl";
|
||||
self.pos1 = '-16 -16 0';
|
||||
self.pos2 = '16 16 16';
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_enforcer_dead_1 (1 0 0) (-16 -16 -24) (16 16 0) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path":"progs/enforcer.mdl","frame":54});
|
||||
}
|
||||
Dead Enforcer
|
||||
*/
|
||||
void() misc_enforcer_dead_1 =
|
||||
{
|
||||
self.mdl = "progs/enforcer.mdl";
|
||||
self.pos1 = '-16 -16 -24';
|
||||
self.pos2 = '16 16 0';
|
||||
self.frame = 54;
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_enforcer_dead_2 (1 0 0) (-16 -16 -24) (16 16 0) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path":"progs/enforcer.mdl","frame":65});
|
||||
}
|
||||
Dead Enforcer
|
||||
*/
|
||||
void() misc_enforcer_dead_2 =
|
||||
{
|
||||
self.mdl = "progs/enforcer.mdl";
|
||||
self.pos1 = '-16 -16 -24';
|
||||
self.pos2 = '16 16 0';
|
||||
self.frame = 65;
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_enforcer_head (1 0 0) (-16 -16 0) (16 16 16) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ("progs/h_mega.mdl");
|
||||
}
|
||||
Enforcer Head
|
||||
*/
|
||||
void() misc_enforcer_head =
|
||||
{
|
||||
self.mdl = "progs/h_mega.mdl";
|
||||
self.pos1 = '-16 -16 0';
|
||||
self.pos2 = '16 16 16';
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_fish_dead (1 0 0) (-16 -16 -24) (16 16 0) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path":"progs/fish.mdl","frame":38});
|
||||
}
|
||||
Dead Fish
|
||||
*/
|
||||
void() misc_fish_dead =
|
||||
{
|
||||
self.mdl = "progs/fish.mdl";
|
||||
self.pos1 = '-16 -16 -24';
|
||||
self.pos2 = '16 16 0';
|
||||
self.frame = 38;
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_hknight_dead_1 (1 0 0) (-16 -16 -24) (16 16 0) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path":"progs/hknight.mdl","frame":53});
|
||||
}
|
||||
Dead Death Knight
|
||||
*/
|
||||
void() misc_hknight_dead_1 =
|
||||
{
|
||||
self.mdl = "progs/hknight.mdl";
|
||||
self.pos1 = '-16 -16 -24';
|
||||
self.pos2 = '16 16 0';
|
||||
self.frame = 53;
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_hknight_dead_2 (1 0 0) (-16 -16 -24) (16 16 0) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path":"progs/hknight.mdl","frame":62});
|
||||
}
|
||||
Dead Death Knight
|
||||
*/
|
||||
void() misc_hknight_dead_2 =
|
||||
{
|
||||
self.mdl = "progs/hknight.mdl";
|
||||
self.pos1 = '-16 -16 -24';
|
||||
self.pos2 = '16 16 0';
|
||||
self.frame = 62;
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_hknight_head (1 0 0) (-16 -16 0) (16 16 16) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ("progs/h_hellkn.mdl");
|
||||
}
|
||||
Death Knight Head
|
||||
*/
|
||||
void() misc_hknight_head =
|
||||
{
|
||||
self.mdl = "progs/h_hellkn.mdl";
|
||||
self.pos1 = '-16 -16 0';
|
||||
self.pos2 = '16 16 16';
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_knight_dead_1 (1 0 0) (-16 -16 -24) (16 16 0) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path":"progs/knight.mdl","frame":85});
|
||||
}
|
||||
Dead Knight
|
||||
*/
|
||||
void() misc_knight_dead_1 =
|
||||
{
|
||||
self.mdl = "progs/knight.mdl";
|
||||
self.pos1 = '-16 -16 -24';
|
||||
self.pos2 = '16 16 0';
|
||||
self.frame = 85;
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_knight_dead_2 (1 0 0) (-16 -16 -24) (16 16 0) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path":"progs/knight.mdl","frame":96});
|
||||
}
|
||||
Dead Knight
|
||||
*/
|
||||
void() misc_knight_dead_2 =
|
||||
{
|
||||
self.mdl = "progs/knight.mdl";
|
||||
self.pos1 = '-16 -16 -24';
|
||||
self.pos2 = '16 16 0';
|
||||
self.frame = 96;
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_knight_head (1 0 0) (-16 -16 0) (16 16 16) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ("progs/h_knight.mdl");
|
||||
}
|
||||
Knight Head
|
||||
*/
|
||||
void() misc_knight_head =
|
||||
{
|
||||
self.mdl = "progs/h_knight.mdl";
|
||||
self.pos1 = '-16 -16 0';
|
||||
self.pos2 = '16 16 16';
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_ogre_dead_1 (1 0 0) (-32 -32 -24) (32 32 0) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path":"progs/ogre.mdl","frame":125});
|
||||
}
|
||||
Dead Ogre
|
||||
*/
|
||||
void() misc_ogre_dead_1 =
|
||||
{
|
||||
self.mdl = "progs/ogre.mdl";
|
||||
self.pos1 = '-32 -32 -24';
|
||||
self.pos2 = '32 32 0';
|
||||
self.frame = 125;
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_ogre_dead_2 (1 0 0) (-32 -32 -24) (32 32 0) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path":"progs/ogre.mdl","frame":135});
|
||||
}
|
||||
Dead Ogre
|
||||
*/
|
||||
void() misc_ogre_dead_2 =
|
||||
{
|
||||
self.mdl = "progs/ogre.mdl";
|
||||
self.pos1 = '-32 -32 -24';
|
||||
self.pos2 = '32 32 0';
|
||||
self.frame = 135;
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_ogre_head (1 0 0) (-16 -16 0) (16 16 16) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ("progs/h_ogre.mdl");
|
||||
}
|
||||
Ogre Head
|
||||
*/
|
||||
void() misc_ogre_head =
|
||||
{
|
||||
self.mdl = "progs/h_ogre.mdl";
|
||||
self.pos1 = '-16 -16 0';
|
||||
self.pos2 = '16 16 16';
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_shalrath_dead (1 0 0) (-32 -32 -24) (32 32 0) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path":"progs/shalrath.mdl","frame":22});
|
||||
}
|
||||
Dead Vore
|
||||
*/
|
||||
void() misc_shalrath_dead =
|
||||
{
|
||||
self.mdl = "progs/shalrath.mdl";
|
||||
self.pos1 = '-32 -32 -24';
|
||||
self.pos2 = '32 32 0';
|
||||
self.frame = 22;
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_shalrath_head (1 0 0) (-16 -16 0) (16 16 16) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ("progs/h_shal.mdl");
|
||||
}
|
||||
Vore Head
|
||||
*/
|
||||
void() misc_shalrath_head =
|
||||
{
|
||||
self.mdl = "progs/h_shal.mdl";
|
||||
self.pos1 = '-16 -16 0';
|
||||
self.pos2 = '16 16 16';
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_shambler_dead (1 0 0) (-32 -32 -24) (32 32 0) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path":"progs/shambler.mdl","frame":93});
|
||||
}
|
||||
Dead Shambler
|
||||
*/
|
||||
void() misc_shambler_dead =
|
||||
{
|
||||
self.mdl = "progs/shambler.mdl";
|
||||
self.pos1 = '-32 -32 -24';
|
||||
self.pos2 = '32 32 0';
|
||||
self.frame = 93;
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_shambler_head (1 0 0) (-16 -16 0) (16 16 16) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ("progs/h_shams.mdl");
|
||||
}
|
||||
Shambler Head
|
||||
*/
|
||||
void() misc_shambler_head =
|
||||
{
|
||||
self.mdl = "progs/h_shams.mdl";
|
||||
self.pos1 = '-16 -16 0';
|
||||
self.pos2 = '16 16 16';
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_soldier_dead_1 (1 0 0) (-16 -16 -24) (16 16 0) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path":"progs/soldier.mdl","frame":28});
|
||||
}
|
||||
Dead Grunt
|
||||
*/
|
||||
void() misc_soldier_dead_1 =
|
||||
{
|
||||
self.mdl = "progs/soldier.mdl";
|
||||
self.pos1 = '-16 -16 -24';
|
||||
self.pos2 = '16 16 0';
|
||||
self.frame = 17;
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_soldier_dead_2 (1 0 0) (-16 -16 -24) (16 16 0) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path":"progs/soldier.mdl","frame":28});
|
||||
}
|
||||
Dead Grunt
|
||||
*/
|
||||
void() misc_soldier_dead_2 =
|
||||
{
|
||||
self.mdl = "progs/soldier.mdl";
|
||||
self.pos1 = '-16 -16 -24';
|
||||
self.pos2 = '16 16 0';
|
||||
self.frame = 28;
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_soldier_head (1 0 0) (-16 -16 0) (16 16 16) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ("progs/h_guard.mdl");
|
||||
}
|
||||
Grunt Head
|
||||
*/
|
||||
void() misc_soldier_head =
|
||||
{
|
||||
self.mdl = "progs/h_guard.mdl";
|
||||
self.pos1 = '-16 -16 0';
|
||||
self.pos2 = '16 16 16';
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_wizard_dead (1 0 0) (-16 -16 -24) (16 16 0) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path":"progs/wizard.mdl","frame":53});
|
||||
}
|
||||
Dead Scrag
|
||||
*/
|
||||
void() misc_wizard_dead =
|
||||
{
|
||||
self.mdl = "progs/wizard.mdl";
|
||||
self.pos1 = '-16 -16 -24';
|
||||
self.pos2 = '16 16 0';
|
||||
self.frame = 53;
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_wizard_head (1 0 0) (-16 -16 0) (16 16 16) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ("progs/h_wizard.mdl");
|
||||
}
|
||||
Scrag Head
|
||||
*/
|
||||
void() misc_wizard_head =
|
||||
{
|
||||
self.mdl = "progs/h_wizard.mdl";
|
||||
self.pos1 = '-16 -16 0';
|
||||
self.pos2 = '16 16 16';
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_zombie_dead (1 0 0) (-16 -16 -24) (16 16 0) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ({"path":"progs/zombie.mdl","frame":172});
|
||||
}
|
||||
Dead Zombie
|
||||
*/
|
||||
void() misc_zombie_dead =
|
||||
{
|
||||
self.mdl = "progs/zombie.mdl";
|
||||
self.pos1 = '-16 -16 -24';
|
||||
self.pos2 = '16 16 0';
|
||||
self.frame = 172;
|
||||
misc_model();
|
||||
};
|
||||
|
||||
/*QUAKED misc_zombie_head (1 0 0) (-16 -16 0) (16 16 16) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model ("progs/h_zombie.mdl");
|
||||
}
|
||||
Zombie Head
|
||||
*/
|
||||
void() misc_zombie_head =
|
||||
{
|
||||
self.mdl = "progs/h_zombie.mdl";
|
||||
self.pos1 = '-16 -16 0';
|
||||
self.pos2 = '16 16 16';
|
||||
misc_model();
|
||||
};
|
||||
189
mod_slipgate/source/server/monsters.qc
Normal file
189
mod_slipgate/source/server/monsters.qc
Normal file
@@ -0,0 +1,189 @@
|
||||
enumflags { MONSTER_AMBUSH, MONSTER_TELEPORT=4 };
|
||||
|
||||
/*==========
|
||||
monster_death_use
|
||||
|
||||
when a monster dies, it fires it's targets with its enemy as the activator
|
||||
==========*/
|
||||
void() monster_death_use =
|
||||
{
|
||||
// drop to floor
|
||||
if (self.flags & FL_FLY)
|
||||
self.flags = self.flags - FL_FLY;
|
||||
if (self.flags & FL_SWIM)
|
||||
self.flags = self.flags - FL_SWIM;
|
||||
|
||||
// use targets
|
||||
activator = self.enemy;
|
||||
UseTargets();
|
||||
|
||||
// bump monster counter
|
||||
killed_monsters = killed_monsters + 1;
|
||||
WriteByte (MSG_ALL, SVC_KILLEDMONSTER);
|
||||
};
|
||||
|
||||
/*==========
|
||||
monster_use
|
||||
|
||||
using a monster makes it angry if the activator is a player
|
||||
==========*/
|
||||
static void() monster_use =
|
||||
{
|
||||
if (self.enemy)
|
||||
return;
|
||||
if (self.health <= 0)
|
||||
return;
|
||||
if (activator.classname != "player")
|
||||
return;
|
||||
if (activator.items & IT_INVISIBILITY)
|
||||
return;
|
||||
if (activator.flags & FL_NOTARGET)
|
||||
return;
|
||||
|
||||
self.enemy = activator;
|
||||
self.nextthink = time + 0.1;
|
||||
self.think = FoundTarget;
|
||||
};
|
||||
|
||||
/*==========
|
||||
monster_start_go
|
||||
==========*/
|
||||
static void() monster_start_go =
|
||||
{
|
||||
// only walkmonsters drop to the floor
|
||||
if (self.flags & (FL_MONSTER | FL_FLY | FL_SWIM) == FL_MONSTER)
|
||||
{
|
||||
self.origin_z = self.origin_z + 1;
|
||||
droptofloor();
|
||||
}
|
||||
|
||||
// print console warning if we're stuck in a wall
|
||||
if (!walkmove(0, 0))
|
||||
{
|
||||
dprint(self.classname);
|
||||
dprint(" in wall at: ");
|
||||
dprint(vtos(self.origin));
|
||||
dprint("\n");
|
||||
}
|
||||
|
||||
self.think = self.th_stand;
|
||||
self.nextthink = time + 0.01 + random() * 0.5;
|
||||
|
||||
// if the monster targets a path corner, they will move towards it
|
||||
// otherwise, they will fire their targets upon death
|
||||
if (self.target != "")
|
||||
{
|
||||
entity t = find(world, targetname, self.target);
|
||||
if (!t)
|
||||
{
|
||||
dprint(self.classname);
|
||||
dprint (" can't find target at: ");
|
||||
dprint (vtos(self.origin));
|
||||
dprint ("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (t.classname == "path_corner")
|
||||
{
|
||||
self.movetarget = self.goalentity = t;
|
||||
self.ideal_yaw = vectoyaw(t.origin - self.origin);
|
||||
self.think = self.th_walk;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*==========
|
||||
monster_teleport_use
|
||||
|
||||
using a monster with the teleport flag spawns it in
|
||||
==========*/
|
||||
static void() monster_teleport_use =
|
||||
{
|
||||
self.use = monster_use;
|
||||
self.takedamage = DAMAGE_AIM;
|
||||
self.solid = SOLID_SLIDEBOX;
|
||||
self.movetype = MOVETYPE_STEP;
|
||||
setmodel(self, self.mdl);
|
||||
setsize(self, self.pos1, self.pos2);
|
||||
|
||||
spawn_tdeath(self.origin, self);
|
||||
spawn_tfog(self.origin);
|
||||
|
||||
self.think = self.th_stand;
|
||||
self.nextthink = time + 0.1;
|
||||
|
||||
// if a player activated the monster,
|
||||
// get mad unless they're invisible or notarget
|
||||
if (activator.classname == "player")
|
||||
{
|
||||
if (activator.flags & FL_NOTARGET)
|
||||
return;
|
||||
if (activator.items & IT_INVISIBILITY)
|
||||
return;
|
||||
self.enemy = activator;
|
||||
self.think = FoundTarget;
|
||||
self.nextthink = time + 0.1;
|
||||
}
|
||||
};
|
||||
|
||||
/*==========
|
||||
monster_start
|
||||
==========*/
|
||||
void(string mod, string hmod, float hp, float fl, vector min, vector max) monster_start =
|
||||
{
|
||||
total_monsters = total_monsters + 1;
|
||||
|
||||
self.flags = FL_MONSTER + fl; // FL_FLY or FL_SWIM
|
||||
self.headmodel = hmod;
|
||||
self.health = hp;
|
||||
|
||||
if (self.flags & FL_FLY)
|
||||
{
|
||||
self.yaw_speed = 20;
|
||||
self.view_ofs = '0 0 25';
|
||||
}
|
||||
else if (self.flags & FL_SWIM)
|
||||
{
|
||||
self.yaw_speed = 10;
|
||||
self.view_ofs = '0 0 10';
|
||||
}
|
||||
else
|
||||
{
|
||||
self.yaw_speed = 30;
|
||||
self.view_ofs = '0 0 25';
|
||||
}
|
||||
self.ideal_yaw = self.angles_y;
|
||||
|
||||
// teleport flag
|
||||
if (self.spawnflags & MONSTER_TELEPORT)
|
||||
{
|
||||
if (!self.targetname)
|
||||
{
|
||||
total_monsters = total_monsters - 1;
|
||||
objerror("teleporting monsters must have a targetname\n");
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
|
||||
self.use = monster_teleport_use;
|
||||
self.solid = SOLID_NOT;
|
||||
self.movetype = MOVETYPE_NONE;
|
||||
setsize(self, min, max);
|
||||
// save off fields so we can restore them later
|
||||
self.pos1 = min;
|
||||
self.pos2 = max;
|
||||
self.mdl = mod;
|
||||
return;
|
||||
}
|
||||
|
||||
self.solid = SOLID_SLIDEBOX;
|
||||
self.movetype = MOVETYPE_STEP;
|
||||
setmodel (self, mod);
|
||||
setsize (self, min, max);
|
||||
|
||||
self.use = monster_use;
|
||||
self.takedamage = DAMAGE_AIM;
|
||||
|
||||
self.think = monster_start_go;
|
||||
self.nextthink = time + 0.01 + random() * 0.5;
|
||||
};
|
||||
381
mod_slipgate/source/server/monsters/boss.qc
Normal file
381
mod_slipgate/source/server/monsters/boss.qc
Normal file
@@ -0,0 +1,381 @@
|
||||
$frame rise1 rise2 rise3 rise4 rise5 rise6 rise7 rise8 rise9 rise10
|
||||
$frame rise11 rise12 rise13 rise14 rise15 rise16 rise17
|
||||
|
||||
$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8
|
||||
$frame walk9 walk10 walk11 walk12 walk13 walk14 walk15
|
||||
$frame walk16 walk17 walk18 walk19 walk20 walk21 walk22
|
||||
$frame walk23 walk24 walk25 walk26 walk27 walk28 walk29 walk30 walk31
|
||||
|
||||
$frame death1 death2 death3 death4 death5 death6 death7 death8 death9
|
||||
|
||||
$frame attack1 attack2 attack3 attack4 attack5 attack6 attack7 attack8
|
||||
$frame attack9 attack10 attack11 attack12 attack13 attack14 attack15
|
||||
$frame attack16 attack17 attack18 attack19 attack20 attack21 attack22
|
||||
$frame attack23
|
||||
|
||||
$frame shocka1 shocka2 shocka3 shocka4 shocka5 shocka6 shocka7 shocka8
|
||||
$frame shocka9 shocka10
|
||||
|
||||
$frame shockb1 shockb2 shockb3 shockb4 shockb5 shockb6
|
||||
|
||||
$frame shockc1 shockc2 shockc3 shockc4 shockc5 shockc6 shockc7 shockc8
|
||||
$frame shockc9 shockc10
|
||||
|
||||
#define CHTHON_M_VEL 300
|
||||
|
||||
void() boss_missile1;
|
||||
|
||||
/*==========
|
||||
boss_idle
|
||||
==========*/
|
||||
void() boss_idle =
|
||||
{
|
||||
// look for a new player in co-op
|
||||
if (coop)
|
||||
{
|
||||
entity client = checkclient();
|
||||
if (client)
|
||||
{
|
||||
if (visible(client))
|
||||
{
|
||||
self.enemy = client;
|
||||
boss_missile1();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.walkframe = self.walkframe + 1;
|
||||
if (self.walkframe > 30)
|
||||
self.walkframe = 0;
|
||||
self.frame = $walk1 + self.walkframe;
|
||||
|
||||
self.think = boss_idle;
|
||||
self.nextthink = time + 0.1;
|
||||
};
|
||||
|
||||
void() boss_rise1 =[ $rise1, boss_rise2 ] {te_lavasplash(self.origin);sound(self, CHAN_BODY, "boss1/out1.wav", 1, ATTN_NORM);};
|
||||
void() boss_rise2 =[ $rise2, boss_rise3 ] {};
|
||||
void() boss_rise3 =[ $rise3, boss_rise4 ] {};
|
||||
void() boss_rise4 =[ $rise4, boss_rise5 ] {};
|
||||
void() boss_rise5 =[ $rise5, boss_rise6 ] {sound (self, CHAN_VOICE, "boss1/sight1.wav", 1, ATTN_NORM);};
|
||||
void() boss_rise6 =[ $rise6, boss_rise7 ] {};
|
||||
void() boss_rise7 =[ $rise7, boss_rise8 ] {};
|
||||
void() boss_rise8 =[ $rise8, boss_rise9 ] {};
|
||||
void() boss_rise9 =[ $rise9, boss_rise10 ] {};
|
||||
void() boss_rise10 =[ $rise10, boss_rise11 ] {};
|
||||
void() boss_rise11 =[ $rise11, boss_rise12 ] {};
|
||||
void() boss_rise12 =[ $rise12, boss_rise13 ] {};
|
||||
void() boss_rise13 =[ $rise13, boss_rise14 ] {};
|
||||
void() boss_rise14 =[ $rise14, boss_rise15 ] {};
|
||||
void() boss_rise15 =[ $rise15, boss_rise16 ] {};
|
||||
void() boss_rise16 =[ $rise16, boss_rise17 ] {};
|
||||
void() boss_rise17 =[ $rise17, boss_missile1 ] {};
|
||||
|
||||
/*==========
|
||||
boss_missile
|
||||
==========*/
|
||||
void(float ofs) boss_missile =
|
||||
{
|
||||
sound (self, CHAN_WEAPON, "boss1/throw.wav", 1, ATTN_NORM);
|
||||
|
||||
makevectors(self.angles);
|
||||
vector org = self.origin + v_forward * 100 + v_right * ofs + v_up * self.view_ofs_z;
|
||||
|
||||
vector d;
|
||||
// lead the player on hard mode
|
||||
if (skill > 1)
|
||||
{
|
||||
float t = vlen(self.enemy.origin + self.enemy.view_ofs - org) / CHTHON_M_VEL;
|
||||
vector vec = self.enemy.velocity;
|
||||
vec_z = 0;
|
||||
d = self.enemy.origin + self.enemy.view_ofs + (t * vec);
|
||||
}
|
||||
else
|
||||
d = self.enemy.origin + self.enemy.view_ofs;
|
||||
|
||||
vec = normalize(d - org);
|
||||
launch_spike (org, vec);
|
||||
setmodel (newmis, "progs/lavaball.mdl");
|
||||
setsize (newmis, '0 0 0', '0 0 0');
|
||||
newmis.avelocity = '200 100 300';
|
||||
newmis.velocity = vec * CHTHON_M_VEL;
|
||||
newmis.touch = T_MissileTouch;
|
||||
};
|
||||
|
||||
/*==========
|
||||
boss_check_enemy
|
||||
==========*/
|
||||
void() boss_check_enemy =
|
||||
{
|
||||
// look for a new player in coop
|
||||
if (coop)
|
||||
{
|
||||
// randomly switch, or switch when player is dead
|
||||
if (random() < 0.5 || self.enemy.health <= 0)
|
||||
{
|
||||
entity client = checkclient();
|
||||
if (!client)
|
||||
{
|
||||
if (self.enemy.health > 0)
|
||||
return;
|
||||
|
||||
// go to idle, no live players found
|
||||
self.enemy = world;
|
||||
boss_idle();
|
||||
return;
|
||||
}
|
||||
self.enemy = client;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// go to idle in single player if the player is dead
|
||||
if (self.enemy.health <= 0)
|
||||
{
|
||||
self.enemy = world;
|
||||
boss_idle();
|
||||
}
|
||||
};
|
||||
|
||||
void() boss_missile1 =[ $attack1, boss_missile2 ] {ai_face();};
|
||||
void() boss_missile2 =[ $attack2, boss_missile3 ] {ai_face();};
|
||||
void() boss_missile3 =[ $attack3, boss_missile4 ] {ai_face();};
|
||||
void() boss_missile4 =[ $attack4, boss_missile5 ] {ai_face();};
|
||||
void() boss_missile5 =[ $attack5, boss_missile6 ] {ai_face();};
|
||||
void() boss_missile6 =[ $attack6, boss_missile7 ] {ai_face();};
|
||||
void() boss_missile7 =[ $attack7, boss_missile8 ] {ai_face();boss_missile(100);};
|
||||
void() boss_missile8 =[ $attack8, boss_missile9 ] {ai_face();};
|
||||
void() boss_missile9 =[ $attack9, boss_missile10 ] {ai_face();};
|
||||
void() boss_missile10 =[ $attack10, boss_missile11 ] {ai_face();};
|
||||
void() boss_missile11 =[ $attack11, boss_missile12 ] {ai_face();};
|
||||
void() boss_missile12 =[ $attack12, boss_missile13 ] {ai_face();};
|
||||
void() boss_missile13 =[ $attack13, boss_missile14 ] {ai_face();};
|
||||
void() boss_missile14 =[ $attack14, boss_missile15 ] {ai_face();};
|
||||
void() boss_missile15 =[ $attack15, boss_missile16 ] {ai_face();};
|
||||
void() boss_missile16 =[ $attack16, boss_missile17 ] {ai_face();};
|
||||
void() boss_missile17 =[ $attack17, boss_missile18 ] {ai_face();};
|
||||
void() boss_missile18 =[ $attack18, boss_missile19 ] {ai_face();boss_missile(-100);};
|
||||
void() boss_missile19 =[ $attack19, boss_missile20 ] {ai_face();};
|
||||
void() boss_missile20 =[ $attack20, boss_missile21 ] {ai_face();};
|
||||
void() boss_missile21 =[ $attack21, boss_missile22 ] {ai_face();};
|
||||
void() boss_missile22 =[ $attack22, boss_missile23 ] {ai_face();};
|
||||
void() boss_missile23 =[ $attack23, boss_missile1 ] {ai_face();boss_check_enemy();};
|
||||
|
||||
void() boss_shocka1 =[ $shocka1, boss_shocka2 ] {};
|
||||
void() boss_shocka2 =[ $shocka2, boss_shocka3 ] {};
|
||||
void() boss_shocka3 =[ $shocka3, boss_shocka4 ] {};
|
||||
void() boss_shocka4 =[ $shocka4, boss_shocka5 ] {};
|
||||
void() boss_shocka5 =[ $shocka5, boss_shocka6 ] {};
|
||||
void() boss_shocka6 =[ $shocka6, boss_shocka7 ] {};
|
||||
void() boss_shocka7 =[ $shocka7, boss_shocka8 ] {};
|
||||
void() boss_shocka8 =[ $shocka8, boss_shocka9 ] {};
|
||||
void() boss_shocka9 =[ $shocka9, boss_shocka10 ] {};
|
||||
void() boss_shocka10 =[ $shocka10, boss_missile1 ] {};
|
||||
|
||||
void() boss_shockb1 =[ $shockb1, boss_shockb2 ] {};
|
||||
void() boss_shockb2 =[ $shockb2, boss_shockb3 ] {};
|
||||
void() boss_shockb3 =[ $shockb3, boss_shockb4 ] {};
|
||||
void() boss_shockb4 =[ $shockb4, boss_shockb5 ] {};
|
||||
void() boss_shockb5 =[ $shockb5, boss_shockb6 ] {};
|
||||
void() boss_shockb6 =[ $shockb6, boss_shockb7 ] {};
|
||||
void() boss_shockb7 =[ $shockb1, boss_shockb8 ] {};
|
||||
void() boss_shockb8 =[ $shockb2, boss_shockb9 ] {};
|
||||
void() boss_shockb9 =[ $shockb3, boss_shockb10 ] {};
|
||||
void() boss_shockb10 =[ $shockb4, boss_missile1 ] {};
|
||||
|
||||
void() boss_shockc1 =[ $shockc1, boss_shockc2 ] {};
|
||||
void() boss_shockc2 =[ $shockc2, boss_shockc3 ] {};
|
||||
void() boss_shockc3 =[ $shockc3, boss_shockc4 ] {};
|
||||
void() boss_shockc4 =[ $shockc4, boss_shockc5 ] {};
|
||||
void() boss_shockc5 =[ $shockc5, boss_shockc6 ] {};
|
||||
void() boss_shockc6 =[ $shockc6, boss_shockc7 ] {};
|
||||
void() boss_shockc7 =[ $shockc7, boss_shockc8 ] {};
|
||||
void() boss_shockc8 =[ $shockc8, boss_shockc9 ] {};
|
||||
void() boss_shockc9 =[ $shockc9, boss_shockc10 ] {};
|
||||
void() boss_shockc10 =[ $shockc10, boss_death1 ] {};
|
||||
|
||||
void() boss_death1 = [$death1, boss_death2] {sound (self, CHAN_VOICE, "boss1/death.wav", 1, ATTN_NORM);};
|
||||
void() boss_death2 = [$death2, boss_death3] {};
|
||||
void() boss_death3 = [$death3, boss_death4] {};
|
||||
void() boss_death4 = [$death4, boss_death5] {};
|
||||
void() boss_death5 = [$death5, boss_death6] {};
|
||||
void() boss_death6 = [$death6, boss_death7] {};
|
||||
void() boss_death7 = [$death7, boss_death8] {};
|
||||
void() boss_death8 = [$death8, boss_death9] {te_lavasplash(self.origin);sound (self, CHAN_BODY, "boss1/out1.wav", 1, ATTN_NORM);};
|
||||
void() boss_death9 = [$death9, boss_death10] {};
|
||||
void() boss_death10 = [$death9, boss_death10]
|
||||
{
|
||||
// bump kill counter
|
||||
killed_monsters = killed_monsters + 1;
|
||||
WriteByte (MSG_ALL, SVC_KILLEDMONSTER);
|
||||
|
||||
// use targets
|
||||
activator = self.enemy;
|
||||
UseTargets();
|
||||
|
||||
remove(self);
|
||||
};
|
||||
|
||||
/*==========
|
||||
boss_awake
|
||||
==========*/
|
||||
void() boss_awake =
|
||||
{
|
||||
self.health = skill + 1;
|
||||
self.yaw_speed = 20;
|
||||
self.view_ofs = '0 0 200';
|
||||
|
||||
if (activator.classname == "player")
|
||||
self.enemy = activator;
|
||||
|
||||
self.solid = SOLID_SLIDEBOX;
|
||||
self.movetype = MOVETYPE_STEP;
|
||||
self.takedamage = DAMAGE_NO;
|
||||
setmodel (self, "progs/boss.mdl");
|
||||
setsize (self, '-128 -128 -24', '128 128 256');
|
||||
|
||||
boss_rise1();
|
||||
};
|
||||
|
||||
/*QUAKED monster_boss (1 0 0) (-128 -128 -24) (128 128 256)
|
||||
{
|
||||
model ("progs/boss.mdl");
|
||||
}
|
||||
Chthon, for Boss levels.
|
||||
Must be triggered to activate.
|
||||
*/
|
||||
void() monster_boss =
|
||||
{
|
||||
if (deathmatch)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
precache_model ("progs/boss.mdl");
|
||||
precache_model ("progs/lavaball.mdl");
|
||||
|
||||
precache_sound ("boss1/out1.wav");
|
||||
precache_sound ("boss1/sight1.wav");
|
||||
precache_sound ("boss1/throw.wav");
|
||||
precache_sound ("boss1/pain.wav");
|
||||
precache_sound ("boss1/death.wav");
|
||||
precache_sound ("misc/power.wav");
|
||||
|
||||
total_monsters = total_monsters + 1;
|
||||
|
||||
self.use = boss_awake;
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void() lightning_use;
|
||||
|
||||
/*==========
|
||||
lightning_fire
|
||||
==========*/
|
||||
void() lightning_fire =
|
||||
{
|
||||
// return electrodes when the bolt is done
|
||||
if (time >= self.attack_finished)
|
||||
{
|
||||
self.state = 0;
|
||||
entity oself = self;
|
||||
self = self.target1;
|
||||
door_go_down ();
|
||||
self = oself.target2;
|
||||
door_go_down ();
|
||||
return;
|
||||
}
|
||||
|
||||
// use two beams that meet in the middle, rather than the
|
||||
// hack of making a single beam shorter
|
||||
te_lightning3(self.pos1, self.pos2, self.target1);
|
||||
te_lightning3(self.pos2, self.origin, self.target2);
|
||||
|
||||
self.nextthink = time + 0.1;
|
||||
self.think = lightning_fire;
|
||||
};
|
||||
|
||||
/*==========
|
||||
lightning_use
|
||||
==========*/
|
||||
void() lightning_use =
|
||||
{
|
||||
if (self.state)
|
||||
return;
|
||||
|
||||
// check the electrodes are aligned and not moving
|
||||
if (self.target1.state != self.target2.state)
|
||||
return;
|
||||
if (self.target1.state != STATE_BOTTOM && self.target1.state != STATE_TOP)
|
||||
return;
|
||||
|
||||
self.state = 1;
|
||||
|
||||
// don't let the electrodes go back up until the bolt is done
|
||||
self.target1.nextthink = -1;
|
||||
self.target2.nextthink = -1;
|
||||
self.attack_finished = time + 1;
|
||||
|
||||
// find the position of the electrodes and then move the
|
||||
// event_lightning entity to the middle of the electrodes.
|
||||
// this is because e1m7 annoyingly has it positioned to the left of the
|
||||
// button so the sound of the lightning is always panned incorrectly!
|
||||
self.pos1 = (self.target1.mins + self.target1.maxs) * 0.5;
|
||||
self.pos1_z = self.target1.absmin_z - 16;
|
||||
self.pos2 = (self.target2.mins + self.target2.maxs) * 0.5;
|
||||
self.pos2_z = self.target2.absmin_z - 16;
|
||||
float len = vlen(self.pos2 - self.pos1);
|
||||
vector dir = normalize(self.pos2 - self.pos1);
|
||||
setorigin(self, self.pos1 + dir * len * 0.5);
|
||||
sound (self, CHAN_VOICE, "misc/power.wav", 1, ATTN_NONE); // no attenuation
|
||||
lightning_fire();
|
||||
|
||||
// decrease chthon health
|
||||
entity chthon = find (world, classname, "monster_boss");
|
||||
if (!chthon)
|
||||
return;
|
||||
if (self.target1.state == STATE_TOP && chthon.health > 0)
|
||||
{
|
||||
self = chthon;
|
||||
self.enemy = activator;
|
||||
sound (self, CHAN_VOICE, "boss1/pain.wav", 1, ATTN_NORM);
|
||||
self.health = self.health - 1;
|
||||
if (self.health > 1)
|
||||
boss_shocka1();
|
||||
else if (self.health == 1)
|
||||
boss_shockb1();
|
||||
else if (self.health == 0)
|
||||
boss_shockc1();
|
||||
}
|
||||
};
|
||||
|
||||
/*==========
|
||||
event_lightning_go
|
||||
==========*/
|
||||
void() event_lightning_go =
|
||||
{
|
||||
// find electrodes
|
||||
self.target1 = find(world, target, "lightning");
|
||||
self.target2 = find(self.target1, target, "lightning");
|
||||
if (!self.target1 || !self.target2)
|
||||
{
|
||||
objerror("unable to find lightning targets");
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
|
||||
self.use = lightning_use;
|
||||
};
|
||||
|
||||
/*QUAKED event_lightning (0 1 1) (-8 -8 -8) (8 8 8)
|
||||
Triggerable lightning event for Chthon only.
|
||||
You must have two func_door's in the level which both contain a target of "lightning" (not targetname!)
|
||||
*/
|
||||
void() event_lightning =
|
||||
{
|
||||
precache_sound ("misc/power.wav");
|
||||
self.think = event_lightning_go;
|
||||
self.nextthink = time + 0.2;
|
||||
};
|
||||
297
mod_slipgate/source/server/monsters/demon.qc
Normal file
297
mod_slipgate/source/server/monsters/demon.qc
Normal file
@@ -0,0 +1,297 @@
|
||||
$frame stand1 stand2 stand3 stand4 stand5 stand6 stand7 stand8 stand9
|
||||
$frame stand10 stand11 stand12 stand13
|
||||
|
||||
$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8
|
||||
|
||||
$frame run1 run2 run3 run4 run5 run6
|
||||
|
||||
$frame leap1 leap2 leap3 leap4 leap5 leap6 leap7 leap8 leap9 leap10
|
||||
$frame leap11 leap12
|
||||
|
||||
$frame pain1 pain2 pain3 pain4 pain5 pain6
|
||||
|
||||
$frame death1 death2 death3 death4 death5 death6 death7 death8 death9
|
||||
|
||||
$frame attacka1 attacka2 attacka3 attacka4 attacka5 attacka6 attacka7 attacka8
|
||||
$frame attacka9 attacka10 attacka11 attacka12 attacka13 attacka14 attacka15
|
||||
|
||||
void() demon1_stand1 =[ $stand1, demon1_stand2 ] {ai_stand();
|
||||
if (random() < 0.1)
|
||||
sound (self, CHAN_VOICE, "demon/idle1.wav", 1, ATTN_IDLE);
|
||||
};
|
||||
void() demon1_stand2 =[ $stand2, demon1_stand3 ] {ai_stand();};
|
||||
void() demon1_stand3 =[ $stand3, demon1_stand4 ] {ai_stand();};
|
||||
void() demon1_stand4 =[ $stand4, demon1_stand5 ] {ai_stand();};
|
||||
void() demon1_stand5 =[ $stand5, demon1_stand6 ] {ai_stand();};
|
||||
void() demon1_stand6 =[ $stand6, demon1_stand7 ] {ai_stand();};
|
||||
void() demon1_stand7 =[ $stand7, demon1_stand8 ] {ai_stand();};
|
||||
void() demon1_stand8 =[ $stand8, demon1_stand9 ] {ai_stand();};
|
||||
void() demon1_stand9 =[ $stand9, demon1_stand10 ] {ai_stand();};
|
||||
void() demon1_stand10 =[ $stand10, demon1_stand11 ] {ai_stand();};
|
||||
void() demon1_stand11 =[ $stand11, demon1_stand12 ] {ai_stand();};
|
||||
void() demon1_stand12 =[ $stand12, demon1_stand13 ] {ai_stand();};
|
||||
void() demon1_stand13 =[ $stand13, demon1_stand1 ] {ai_stand();};
|
||||
|
||||
void() demon1_walk1 =[ $walk1, demon1_walk2 ] {
|
||||
if (random() < 0.2)
|
||||
sound (self, CHAN_VOICE, "demon/idle1.wav", 1, ATTN_IDLE);
|
||||
ai_walk(8);
|
||||
};
|
||||
void() demon1_walk2 =[ $walk2, demon1_walk3 ] {ai_walk(6);};
|
||||
void() demon1_walk3 =[ $walk3, demon1_walk4 ] {ai_walk(6);};
|
||||
void() demon1_walk4 =[ $walk4, demon1_walk5 ] {ai_walk(7);};
|
||||
void() demon1_walk5 =[ $walk5, demon1_walk6 ] {ai_walk(4);};
|
||||
void() demon1_walk6 =[ $walk6, demon1_walk7 ] {ai_walk(6);};
|
||||
void() demon1_walk7 =[ $walk7, demon1_walk8 ] {ai_walk(10);};
|
||||
void() demon1_walk8 =[ $walk8, demon1_walk1 ] {ai_walk(10);};
|
||||
|
||||
void() demon1_run1 =[ $run1, demon1_run2 ] {
|
||||
if (random() < 0.2)
|
||||
sound (self, CHAN_VOICE, "demon/idle1.wav", 1, ATTN_IDLE);
|
||||
ai_run(20);};
|
||||
void() demon1_run2 =[ $run2, demon1_run3 ] {ai_run(15);};
|
||||
void() demon1_run3 =[ $run3, demon1_run4 ] {ai_run(36);};
|
||||
void() demon1_run4 =[ $run4, demon1_run5 ] {ai_run(20);};
|
||||
void() demon1_run5 =[ $run5, demon1_run6 ] {ai_run(15);};
|
||||
void() demon1_run6 =[ $run6, demon1_run1 ] {ai_run(36);};
|
||||
|
||||
void() demon1_jump1;
|
||||
void() demon1_jump11;
|
||||
|
||||
void() Demon_JumpTouch =
|
||||
{
|
||||
if (self.health <= 0)
|
||||
return;
|
||||
|
||||
if (other.takedamage)
|
||||
{
|
||||
if (vlen(self.velocity) > 400)
|
||||
{
|
||||
float ldmg = 40 + 10 * random();
|
||||
Damage (other, self, self, ldmg);
|
||||
}
|
||||
}
|
||||
|
||||
if (!checkbottom(self))
|
||||
{
|
||||
if (self.flags & FL_ONGROUND)
|
||||
{
|
||||
self.touch = SUB_Null;
|
||||
self.think = demon1_jump1;
|
||||
self.nextthink = time + 0.1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
self.touch = SUB_Null;
|
||||
self.think = demon1_jump11;
|
||||
self.nextthink = time + 0.1;
|
||||
};
|
||||
|
||||
|
||||
|
||||
void() demon1_jump1 =[ $leap1, demon1_jump2 ] {ai_face();};
|
||||
void() demon1_jump2 =[ $leap2, demon1_jump3 ] {ai_face();};
|
||||
void() demon1_jump3 =[ $leap3, demon1_jump4 ] {ai_face();};
|
||||
void() demon1_jump4 =[ $leap4, demon1_jump5 ]
|
||||
{
|
||||
ai_face();
|
||||
|
||||
self.touch = Demon_JumpTouch;
|
||||
makevectors (self.angles);
|
||||
self.origin_z = self.origin_z + 1;
|
||||
self.velocity = v_forward * 600 + '0 0 250';
|
||||
if (self.flags & FL_ONGROUND)
|
||||
self.flags = self.flags - FL_ONGROUND;
|
||||
};
|
||||
void() demon1_jump5 =[ $leap5, demon1_jump6 ] {};
|
||||
void() demon1_jump6 =[ $leap6, demon1_jump7 ] {};
|
||||
void() demon1_jump7 =[ $leap7, demon1_jump8 ] {};
|
||||
void() demon1_jump8 =[ $leap8, demon1_jump9 ] {};
|
||||
void() demon1_jump9 =[ $leap9, demon1_jump10 ] {};
|
||||
void() demon1_jump10 =[ $leap10, demon1_jump1 ] {self.nextthink = time + 3;};
|
||||
void() demon1_jump11 =[ $leap11, demon1_jump12 ] {};
|
||||
void() demon1_jump12 =[ $leap12, demon1_run1 ] {};
|
||||
|
||||
void(float side) Demon_Melee =
|
||||
{
|
||||
ai_face ();
|
||||
walkmove (self.ideal_yaw, 12);
|
||||
|
||||
if (vlen(self.enemy.origin - self.origin) > 100)
|
||||
return;
|
||||
if (!CanDamage (self.enemy, self))
|
||||
return;
|
||||
|
||||
sound (self, CHAN_WEAPON, "demon/dhit2.wav", 1, ATTN_NORM);
|
||||
float ldmg = 10 + 5 * random();
|
||||
Damage (self.enemy, self, self, ldmg);
|
||||
|
||||
makevectors (self.angles);
|
||||
SpawnMeatSpray (self.origin + v_forward*16, side * v_right);
|
||||
};
|
||||
|
||||
|
||||
void() demon1_atta1 =[ $attacka1, demon1_atta2 ] {ai_charge(4);};
|
||||
void() demon1_atta2 =[ $attacka2, demon1_atta3 ] {ai_charge(0);};
|
||||
void() demon1_atta3 =[ $attacka3, demon1_atta4 ] {ai_charge(0);};
|
||||
void() demon1_atta4 =[ $attacka4, demon1_atta5 ] {ai_charge(1);};
|
||||
void() demon1_atta5 =[ $attacka5, demon1_atta6 ] {ai_charge(2); Demon_Melee(200);};
|
||||
void() demon1_atta6 =[ $attacka6, demon1_atta7 ] {ai_charge(1);};
|
||||
void() demon1_atta7 =[ $attacka7, demon1_atta8 ] {ai_charge(6);};
|
||||
void() demon1_atta8 =[ $attacka8, demon1_atta9 ] {ai_charge(8);};
|
||||
void() demon1_atta9 =[ $attacka9, demon1_atta10 ] {ai_charge(4);};
|
||||
void() demon1_atta10 =[ $attacka10, demon1_atta11 ] {ai_charge(2);};
|
||||
void() demon1_atta11 =[ $attacka11, demon1_atta12 ] {Demon_Melee(-200);};
|
||||
void() demon1_atta12 =[ $attacka12, demon1_atta13 ] {ai_charge(5);};
|
||||
void() demon1_atta13 =[ $attacka13, demon1_atta14 ] {ai_charge(8);};
|
||||
void() demon1_atta14 =[ $attacka14, demon1_atta15 ] {ai_charge(4);};
|
||||
void() demon1_atta15 =[ $attacka15, demon1_run1 ] {ai_charge(4);};
|
||||
|
||||
void() demon1_pain1 =[ $pain1, demon1_pain2 ] {};
|
||||
void() demon1_pain2 =[ $pain2, demon1_pain3 ] {};
|
||||
void() demon1_pain3 =[ $pain3, demon1_pain4 ] {};
|
||||
void() demon1_pain4 =[ $pain4, demon1_pain5 ] {};
|
||||
void() demon1_pain5 =[ $pain5, demon1_pain6 ] {};
|
||||
void() demon1_pain6 =[ $pain6, demon1_run1 ] {};
|
||||
|
||||
void(entity attacker, float damage) demon_pain =
|
||||
{
|
||||
if (self.touch == Demon_JumpTouch)
|
||||
return;
|
||||
if (self.pain_finished > time)
|
||||
return;
|
||||
|
||||
self.pain_finished = time + 1;
|
||||
sound (self, CHAN_VOICE, "demon/dpain1.wav", 1, ATTN_NORM);
|
||||
|
||||
if (random()*200 > damage)
|
||||
return; // didn't flinch
|
||||
|
||||
demon1_pain1 ();
|
||||
};
|
||||
|
||||
void() demon1_die1 =[ $death1, demon1_die2 ] {};
|
||||
void() demon1_die2 =[ $death2, demon1_die3 ] {};
|
||||
void() demon1_die3 =[ $death3, demon1_die4 ] {};
|
||||
void() demon1_die4 =[ $death4, demon1_die5 ] {};
|
||||
void() demon1_die5 =[ $death5, demon1_die6 ] {};
|
||||
void() demon1_die6 =[ $death6, demon1_die7 ] {};
|
||||
void() demon1_die7 =[ $death7, demon1_die8 ] {};
|
||||
void() demon1_die8 =[ $death8, demon1_die9 ] {};
|
||||
void() demon1_die9 =[ $death9, demon1_die9 ] {};
|
||||
|
||||
void(entity inflictor, entity attacker) demon_die =
|
||||
{
|
||||
if (self.health < -80)
|
||||
{
|
||||
SpawnGib("progs/gib3.mdl");
|
||||
SpawnGib("progs/gib3.mdl");
|
||||
SpawnGib("progs/gib4.mdl");
|
||||
SpawnGib("progs/gib5.mdl");
|
||||
SpawnGib("progs/blood.mdl");
|
||||
SpawnGib("progs/blood.mdl");
|
||||
BecomeGibs();
|
||||
return;
|
||||
}
|
||||
|
||||
sound (self, CHAN_VOICE, "demon/ddeath.wav", 1, ATTN_NORM);
|
||||
self.solid = SOLID_NOT;
|
||||
demon1_die1 ();
|
||||
};
|
||||
|
||||
void() Demon_MeleeAttack =
|
||||
{
|
||||
sound (self, CHAN_VOICE, "demon/idle1.wav", 1, ATTN_NORM);
|
||||
demon1_atta1 ();
|
||||
};
|
||||
|
||||
/*QUAKED monster_demon1 (1 0 0) (-32 -32 -24) (32 32 64) Ambush
|
||||
{
|
||||
model ("progs/demon.mdl");
|
||||
}
|
||||
Fiend.
|
||||
*/
|
||||
void() monster_demon1 =
|
||||
{
|
||||
if (deathmatch)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
precache_model ("progs/demon.mdl");
|
||||
precache_model ("progs/h_demon.mdl");
|
||||
|
||||
precache_sound ("demon/ddeath.wav");
|
||||
precache_sound ("demon/dhit2.wav");
|
||||
precache_sound ("demon/djump.wav");
|
||||
precache_sound ("demon/dpain1.wav");
|
||||
precache_sound ("demon/idle1.wav");
|
||||
precache_sound ("demon/sight2.wav");
|
||||
|
||||
self.th_stand = demon1_stand1;
|
||||
self.th_walk = demon1_walk1;
|
||||
self.th_run = demon1_run1;
|
||||
self.th_die = demon_die;
|
||||
self.th_melee = Demon_MeleeAttack;
|
||||
self.th_missile = demon1_jump1;
|
||||
self.th_pain = demon_pain;
|
||||
|
||||
monster_start("progs/demon.mdl", "progs/h_demon.mdl", 300, 0, VEC_HULL2_MIN, VEC_HULL2_MAX);
|
||||
};
|
||||
|
||||
float() CheckDemonJump =
|
||||
{
|
||||
vector spot1 = self.origin;
|
||||
vector spot2 = self.enemy.origin;
|
||||
traceline (spot1, spot2, MOVE_MISSILE, self);
|
||||
if (trace_inwater)
|
||||
if (trace_inopen)
|
||||
return FALSE;
|
||||
if (trace_ent != self.enemy)
|
||||
return FALSE;
|
||||
|
||||
// too high above player
|
||||
if (self.origin_z + self.mins_z > self.enemy.origin_z + self.enemy.mins_z + 0.75 * self.enemy.size_z)
|
||||
return FALSE;
|
||||
|
||||
// too low below player
|
||||
if (self.origin_z + self.maxs_z < self.enemy.origin_z + self.enemy.mins_z + 0.25 * self.enemy.size_z)
|
||||
return FALSE;
|
||||
|
||||
vector dist = self.enemy.origin - self.origin;
|
||||
dist_z = 0;
|
||||
float len = vlen(dist);
|
||||
if (len < 100)
|
||||
return FALSE;
|
||||
if (len > 200)
|
||||
{
|
||||
if (random() < 0.9)
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
float() DemonCheckAttack =
|
||||
{
|
||||
if (enemy_range == RANGE_MELEE)
|
||||
{
|
||||
if (CanDamage(self.enemy, self))
|
||||
{
|
||||
self.attack_state = AS_MELEE;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (enemy_range == RANGE_FAR)
|
||||
return FALSE;
|
||||
|
||||
if (CheckDemonJump())
|
||||
{
|
||||
sound (self, CHAN_VOICE, "demon/djump.wav", 1, ATTN_NORM);
|
||||
self.attack_state = AS_MISSILE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
};
|
||||
357
mod_slipgate/source/server/monsters/dog.qc
Normal file
357
mod_slipgate/source/server/monsters/dog.qc
Normal file
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
DOG
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
$cd id1/models/dog
|
||||
$origin 0 0 24
|
||||
$base base
|
||||
$skin skin
|
||||
|
||||
$frame attack1 attack2 attack3 attack4 attack5 attack6 attack7 attack8
|
||||
|
||||
$frame death1 death2 death3 death4 death5 death6 death7 death8 death9
|
||||
|
||||
$frame deathb1 deathb2 deathb3 deathb4 deathb5 deathb6 deathb7 deathb8
|
||||
$frame deathb9
|
||||
|
||||
$frame pain1 pain2 pain3 pain4 pain5 pain6
|
||||
|
||||
$frame painb1 painb2 painb3 painb4 painb5 painb6 painb7 painb8 painb9 painb10
|
||||
$frame painb11 painb12 painb13 painb14 painb15 painb16
|
||||
|
||||
$frame run1 run2 run3 run4 run5 run6 run7 run8 run9 run10 run11 run12
|
||||
|
||||
$frame leap1 leap2 leap3 leap4 leap5 leap6 leap7 leap8 leap9
|
||||
|
||||
$frame stand1 stand2 stand3 stand4 stand5 stand6 stand7 stand8 stand9
|
||||
|
||||
$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8
|
||||
|
||||
|
||||
void() dog_leap1;
|
||||
void() dog_run1;
|
||||
|
||||
/*
|
||||
================
|
||||
dog_bite
|
||||
|
||||
================
|
||||
*/
|
||||
void() dog_bite =
|
||||
{
|
||||
local vector delta;
|
||||
local float ldmg;
|
||||
|
||||
if (!self.enemy)
|
||||
return;
|
||||
|
||||
ai_charge(10);
|
||||
|
||||
if (!CanDamage (self.enemy, self))
|
||||
return;
|
||||
|
||||
delta = self.enemy.origin - self.origin;
|
||||
|
||||
if (vlen(delta) > 100)
|
||||
return;
|
||||
|
||||
ldmg = (random() + random() + random()) * 8;
|
||||
Damage (self.enemy, self, self, ldmg);
|
||||
};
|
||||
|
||||
void() Dog_JumpTouch =
|
||||
{
|
||||
local float ldmg;
|
||||
|
||||
if (self.health <= 0)
|
||||
return;
|
||||
|
||||
if (other.takedamage)
|
||||
{
|
||||
if ( vlen(self.velocity) > 300 )
|
||||
{
|
||||
ldmg = 10 + 10*random();
|
||||
Damage (other, self, self, ldmg);
|
||||
}
|
||||
}
|
||||
|
||||
if (!checkbottom(self))
|
||||
{
|
||||
if (self.flags & FL_ONGROUND)
|
||||
{ // jump randomly to not get hung up
|
||||
//dprint ("popjump\n");
|
||||
self.touch = SUB_Null;
|
||||
self.think = dog_leap1;
|
||||
self.nextthink = time + 0.1;
|
||||
|
||||
// self.velocity_x = (random() - 0.5) * 600;
|
||||
// self.velocity_y = (random() - 0.5) * 600;
|
||||
// self.velocity_z = 200;
|
||||
// self.flags = self.flags - FL_ONGROUND;
|
||||
}
|
||||
return; // not on ground yet
|
||||
}
|
||||
|
||||
self.touch = SUB_Null;
|
||||
self.think = dog_run1;
|
||||
self.nextthink = time + 0.1;
|
||||
};
|
||||
|
||||
|
||||
void() dog_stand1 =[ $stand1, dog_stand2 ] {ai_stand();};
|
||||
void() dog_stand2 =[ $stand2, dog_stand3 ] {ai_stand();};
|
||||
void() dog_stand3 =[ $stand3, dog_stand4 ] {ai_stand();};
|
||||
void() dog_stand4 =[ $stand4, dog_stand5 ] {ai_stand();};
|
||||
void() dog_stand5 =[ $stand5, dog_stand6 ] {ai_stand();};
|
||||
void() dog_stand6 =[ $stand6, dog_stand7 ] {ai_stand();};
|
||||
void() dog_stand7 =[ $stand7, dog_stand8 ] {ai_stand();};
|
||||
void() dog_stand8 =[ $stand8, dog_stand9 ] {ai_stand();};
|
||||
void() dog_stand9 =[ $stand9, dog_stand1 ] {ai_stand();};
|
||||
|
||||
void() dog_walk1 =[ $walk1 , dog_walk2 ] {
|
||||
if (random() < 0.2)
|
||||
sound (self, CHAN_VOICE, "dog/idle.wav", 1, ATTN_IDLE);
|
||||
ai_walk(8);};
|
||||
void() dog_walk2 =[ $walk2 , dog_walk3 ] {ai_walk(8);};
|
||||
void() dog_walk3 =[ $walk3 , dog_walk4 ] {ai_walk(8);};
|
||||
void() dog_walk4 =[ $walk4 , dog_walk5 ] {ai_walk(8);};
|
||||
void() dog_walk5 =[ $walk5 , dog_walk6 ] {ai_walk(8);};
|
||||
void() dog_walk6 =[ $walk6 , dog_walk7 ] {ai_walk(8);};
|
||||
void() dog_walk7 =[ $walk7 , dog_walk8 ] {ai_walk(8);};
|
||||
void() dog_walk8 =[ $walk8 , dog_walk1 ] {ai_walk(8);};
|
||||
|
||||
void() dog_run1 =[ $run1 , dog_run2 ] {
|
||||
if (random() < 0.2)
|
||||
sound (self, CHAN_VOICE, "dog/idle.wav", 1, ATTN_IDLE);
|
||||
ai_run(16);};
|
||||
void() dog_run2 =[ $run2 , dog_run3 ] {ai_run(32);};
|
||||
void() dog_run3 =[ $run3 , dog_run4 ] {ai_run(32);};
|
||||
void() dog_run4 =[ $run4 , dog_run5 ] {ai_run(20);};
|
||||
void() dog_run5 =[ $run5 , dog_run6 ] {ai_run(64);};
|
||||
void() dog_run6 =[ $run6 , dog_run7 ] {ai_run(32);};
|
||||
void() dog_run7 =[ $run7 , dog_run8 ] {ai_run(16);};
|
||||
void() dog_run8 =[ $run8 , dog_run9 ] {ai_run(32);};
|
||||
void() dog_run9 =[ $run9 , dog_run10 ] {ai_run(32);};
|
||||
void() dog_run10 =[ $run10 , dog_run11 ] {ai_run(20);};
|
||||
void() dog_run11 =[ $run11 , dog_run12 ] {ai_run(64);};
|
||||
void() dog_run12 =[ $run12 , dog_run1 ] {ai_run(32);};
|
||||
|
||||
void() dog_atta1 =[ $attack1, dog_atta2 ] {ai_charge(10);};
|
||||
void() dog_atta2 =[ $attack2, dog_atta3 ] {ai_charge(10);};
|
||||
void() dog_atta3 =[ $attack3, dog_atta4 ] {ai_charge(10);};
|
||||
void() dog_atta4 =[ $attack4, dog_atta5 ] {
|
||||
sound (self, CHAN_VOICE, "dog/dattack1.wav", 1, ATTN_NORM);
|
||||
dog_bite();};
|
||||
void() dog_atta5 =[ $attack5, dog_atta6 ] {ai_charge(10);};
|
||||
void() dog_atta6 =[ $attack6, dog_atta7 ] {ai_charge(10);};
|
||||
void() dog_atta7 =[ $attack7, dog_atta8 ] {ai_charge(10);};
|
||||
void() dog_atta8 =[ $attack8, dog_run1 ] {ai_charge(10);};
|
||||
|
||||
void() dog_leap1 =[ $leap1, dog_leap2 ] {ai_face();};
|
||||
void() dog_leap2 =[ $leap2, dog_leap3 ]
|
||||
{
|
||||
ai_face();
|
||||
|
||||
self.touch = Dog_JumpTouch;
|
||||
makevectors (self.angles);
|
||||
self.origin_z = self.origin_z + 1;
|
||||
self.velocity = v_forward * 300 + '0 0 200';
|
||||
if (self.flags & FL_ONGROUND)
|
||||
self.flags = self.flags - FL_ONGROUND;
|
||||
};
|
||||
|
||||
void() dog_leap3 =[ $leap3, dog_leap4 ] {};
|
||||
void() dog_leap4 =[ $leap4, dog_leap5 ] {};
|
||||
void() dog_leap5 =[ $leap5, dog_leap6 ] {};
|
||||
void() dog_leap6 =[ $leap6, dog_leap7 ] {};
|
||||
void() dog_leap7 =[ $leap7, dog_leap8 ] {};
|
||||
void() dog_leap8 =[ $leap8, dog_leap9 ] {};
|
||||
void() dog_leap9 =[ $leap9, dog_leap9 ] {};
|
||||
|
||||
void() dog_pain1 =[ $pain1 , dog_pain2 ] {};
|
||||
void() dog_pain2 =[ $pain2 , dog_pain3 ] {};
|
||||
void() dog_pain3 =[ $pain3 , dog_pain4 ] {};
|
||||
void() dog_pain4 =[ $pain4 , dog_pain5 ] {};
|
||||
void() dog_pain5 =[ $pain5 , dog_pain6 ] {};
|
||||
void() dog_pain6 =[ $pain6 , dog_run1 ] {};
|
||||
|
||||
void() dog_painb1 =[ $painb1 , dog_painb2 ] {};
|
||||
void() dog_painb2 =[ $painb2 , dog_painb3 ] {};
|
||||
void() dog_painb3 =[ $painb3 , dog_painb4 ] {ai_pain(4);};
|
||||
void() dog_painb4 =[ $painb4 , dog_painb5 ] {ai_pain(12);};
|
||||
void() dog_painb5 =[ $painb5 , dog_painb6 ] {ai_pain(12);};
|
||||
void() dog_painb6 =[ $painb6 , dog_painb7 ] {ai_pain(2);};
|
||||
void() dog_painb7 =[ $painb7 , dog_painb8 ] {};
|
||||
void() dog_painb8 =[ $painb8 , dog_painb9 ] {ai_pain(4);};
|
||||
void() dog_painb9 =[ $painb9 , dog_painb10 ] {};
|
||||
void() dog_painb10 =[ $painb10 , dog_painb11 ] {ai_pain(10);};
|
||||
void() dog_painb11 =[ $painb11 , dog_painb12 ] {};
|
||||
void() dog_painb12 =[ $painb12 , dog_painb13 ] {};
|
||||
void() dog_painb13 =[ $painb13 , dog_painb14 ] {};
|
||||
void() dog_painb14 =[ $painb14 , dog_painb15 ] {};
|
||||
void() dog_painb15 =[ $painb15 , dog_painb16 ] {};
|
||||
void() dog_painb16 =[ $painb16 , dog_run1 ] {};
|
||||
|
||||
void(entity attacker, float damage) dog_pain =
|
||||
{
|
||||
sound (self, CHAN_VOICE, "dog/dpain1.wav", 1, ATTN_NORM);
|
||||
|
||||
if (random() > 0.5)
|
||||
dog_pain1 ();
|
||||
else
|
||||
dog_painb1 ();
|
||||
};
|
||||
|
||||
void() dog_die1 =[ $death1, dog_die2 ] {};
|
||||
void() dog_die2 =[ $death2, dog_die3 ] {};
|
||||
void() dog_die3 =[ $death3, dog_die4 ] {};
|
||||
void() dog_die4 =[ $death4, dog_die5 ] {};
|
||||
void() dog_die5 =[ $death5, dog_die6 ] {};
|
||||
void() dog_die6 =[ $death6, dog_die7 ] {};
|
||||
void() dog_die7 =[ $death7, dog_die8 ] {};
|
||||
void() dog_die8 =[ $death8, dog_die9 ] {};
|
||||
void() dog_die9 =[ $death9, dog_die9 ] {};
|
||||
|
||||
void() dog_dieb1 =[ $deathb1, dog_dieb2 ] {};
|
||||
void() dog_dieb2 =[ $deathb2, dog_dieb3 ] {};
|
||||
void() dog_dieb3 =[ $deathb3, dog_dieb4 ] {};
|
||||
void() dog_dieb4 =[ $deathb4, dog_dieb5 ] {};
|
||||
void() dog_dieb5 =[ $deathb5, dog_dieb6 ] {};
|
||||
void() dog_dieb6 =[ $deathb6, dog_dieb7 ] {};
|
||||
void() dog_dieb7 =[ $deathb7, dog_dieb8 ] {};
|
||||
void() dog_dieb8 =[ $deathb8, dog_dieb9 ] {};
|
||||
void() dog_dieb9 =[ $deathb9, dog_dieb9 ] {};
|
||||
|
||||
|
||||
void(entity inflictor, entity attacker) dog_die =
|
||||
{
|
||||
// check for gib
|
||||
if (self.health < -35)
|
||||
{
|
||||
SpawnGib ("progs/gib3.mdl");
|
||||
SpawnGib ("progs/gib3.mdl");
|
||||
SpawnGib ("progs/gib4.mdl");
|
||||
SpawnGib ("progs/gib5.mdl");
|
||||
SpawnGib ("progs/blood.mdl");
|
||||
SpawnGib ("progs/blood.mdl");
|
||||
BecomeGibs ();
|
||||
return;
|
||||
}
|
||||
|
||||
// regular death
|
||||
sound (self, CHAN_VOICE, "dog/ddeath.wav", 1, ATTN_NORM);
|
||||
self.solid = SOLID_NOT;
|
||||
if (random() < 0.5)
|
||||
dog_die1 ();
|
||||
else
|
||||
dog_dieb1 ();
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
/*
|
||||
==============
|
||||
CheckDogMelee
|
||||
|
||||
Returns TRUE if a melee attack would hit right now
|
||||
==============
|
||||
*/
|
||||
float() CheckDogMelee =
|
||||
{
|
||||
if (enemy_range == RANGE_MELEE)
|
||||
{ // FIXME: check canreach
|
||||
self.attack_state = AS_MELEE;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
/*
|
||||
==============
|
||||
CheckDogJump
|
||||
|
||||
==============
|
||||
*/
|
||||
float() CheckDogJump =
|
||||
{
|
||||
local vector dist;
|
||||
local float d;
|
||||
|
||||
if (self.origin_z + self.mins_z > self.enemy.origin_z + self.enemy.mins_z
|
||||
+ 0.75 * self.enemy.size_z)
|
||||
return FALSE;
|
||||
|
||||
if (self.origin_z + self.maxs_z < self.enemy.origin_z + self.enemy.mins_z
|
||||
+ 0.25 * self.enemy.size_z)
|
||||
return FALSE;
|
||||
|
||||
dist = self.enemy.origin - self.origin;
|
||||
dist_z = 0;
|
||||
|
||||
d = vlen(dist);
|
||||
|
||||
if (d < 80)
|
||||
return FALSE;
|
||||
|
||||
if (d > 150)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
float() DogCheckAttack =
|
||||
{
|
||||
// if close enough for slashing, go for it
|
||||
if (CheckDogMelee ())
|
||||
{
|
||||
self.attack_state = AS_MELEE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (CheckDogJump ())
|
||||
{
|
||||
self.attack_state = AS_MISSILE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
|
||||
//===========================================================================
|
||||
|
||||
/*QUAKED monster_dog (1 0 0) (-32 -32 -24) (32 32 40) Ambush
|
||||
{
|
||||
model ("progs/dog.mdl");
|
||||
}
|
||||
Rottweiler.
|
||||
*/
|
||||
void() monster_dog =
|
||||
{
|
||||
if (deathmatch)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
precache_model ("progs/dog.mdl");
|
||||
precache_model ("progs/h_dog.mdl");
|
||||
|
||||
precache_sound ("dog/dattack1.wav");
|
||||
precache_sound ("dog/ddeath.wav");
|
||||
precache_sound ("dog/dpain1.wav");
|
||||
precache_sound ("dog/dsight.wav");
|
||||
precache_sound ("dog/idle.wav");
|
||||
|
||||
self.th_stand = dog_stand1;
|
||||
self.th_walk = dog_walk1;
|
||||
self.th_run = dog_run1;
|
||||
self.th_pain = dog_pain;
|
||||
self.th_die = dog_die;
|
||||
self.th_melee = dog_atta1;
|
||||
self.th_missile = dog_leap1;
|
||||
|
||||
monster_start("progs/dog.mdl", "progs/h_dog.mdl", 25, 0, '-32 -32 -24', '32 32 40');
|
||||
};
|
||||
310
mod_slipgate/source/server/monsters/enforcer.qc
Normal file
310
mod_slipgate/source/server/monsters/enforcer.qc
Normal file
@@ -0,0 +1,310 @@
|
||||
$frame stand1 stand2 stand3 stand4 stand5 stand6 stand7
|
||||
|
||||
$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8 walk9 walk10
|
||||
$frame walk11 walk12 walk13 walk14 walk15 walk16
|
||||
|
||||
$frame run1 run2 run3 run4 run5 run6 run7 run8
|
||||
|
||||
$frame attack1 attack2 attack3 attack4 attack5 attack6
|
||||
$frame attack7 attack8 attack9 attack10
|
||||
|
||||
$frame death1 death2 death3 death4 death5 death6 death7 death8
|
||||
$frame death9 death10 death11 death12 death13 death14
|
||||
|
||||
$frame fdeath1 fdeath2 fdeath3 fdeath4 fdeath5 fdeath6 fdeath7 fdeath8
|
||||
$frame fdeath9 fdeath10 fdeath11
|
||||
|
||||
$frame paina1 paina2 paina3 paina4
|
||||
|
||||
$frame painb1 painb2 painb3 painb4 painb5
|
||||
|
||||
$frame painc1 painc2 painc3 painc4 painc5 painc6 painc7 painc8
|
||||
|
||||
$frame paind1 paind2 paind3 paind4 paind5 paind6 paind7 paind8
|
||||
$frame paind9 paind10 paind11 paind12 paind13 paind14 paind15 paind16
|
||||
$frame paind17 paind18 paind19
|
||||
|
||||
void() Laser_Touch =
|
||||
{
|
||||
if (pointcontents(self.origin) == CONTENT_SKY)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
|
||||
sound (self, CHAN_WEAPON, "enforcer/enfstop.wav", 1, ATTN_STATIC);
|
||||
|
||||
if (other.takedamage)
|
||||
{
|
||||
if (other.classname == "func_breakable")
|
||||
SpawnTouchParticles(15, other.colour);
|
||||
else
|
||||
SpawnTouchblood(15);
|
||||
|
||||
Damage (other, self, self.owner, 15);
|
||||
}
|
||||
else
|
||||
{
|
||||
vector org = self.origin - 8*normalize(self.velocity);
|
||||
te_gunshot(org);
|
||||
}
|
||||
|
||||
remove(self);
|
||||
};
|
||||
|
||||
void(vector org, vector vec) LaunchLaser =
|
||||
{
|
||||
if (self.classname == "monster_enforcer")
|
||||
sound (self, CHAN_WEAPON, "enforcer/enfire.wav", 1, ATTN_NORM);
|
||||
|
||||
vec = normalize(vec);
|
||||
|
||||
newmis = spawn();
|
||||
newmis.owner = self;
|
||||
newmis.movetype = MOVETYPE_FLY;
|
||||
newmis.solid = SOLID_BBOX;
|
||||
newmis.effects = EF_DIMLIGHT;
|
||||
|
||||
setmodel (newmis, "progs/laser.mdl");
|
||||
setsize (newmis, '0 0 0', '0 0 0');
|
||||
setorigin (newmis, org);
|
||||
|
||||
newmis.velocity = vec * 600;
|
||||
newmis.angles = vectoangles(newmis.velocity);
|
||||
|
||||
newmis.nextthink = time + 5;
|
||||
newmis.think = SUB_Remove;
|
||||
newmis.touch = Laser_Touch;
|
||||
};
|
||||
|
||||
void() enforcer_fire =
|
||||
{
|
||||
self.effects = self.effects | EF_MUZZLEFLASH;
|
||||
makevectors (self.angles);
|
||||
vector org = self.origin + v_forward * 30 + v_right * 8.5 + '0 0 16';
|
||||
LaunchLaser(org, self.enemy.origin - self.origin);
|
||||
};
|
||||
|
||||
void() enf_stand1 =[ $stand1, enf_stand2 ] {ai_stand();};
|
||||
void() enf_stand2 =[ $stand2, enf_stand3 ] {ai_stand();};
|
||||
void() enf_stand3 =[ $stand3, enf_stand4 ] {ai_stand();};
|
||||
void() enf_stand4 =[ $stand4, enf_stand5 ] {ai_stand();};
|
||||
void() enf_stand5 =[ $stand5, enf_stand6 ] {ai_stand();};
|
||||
void() enf_stand6 =[ $stand6, enf_stand7 ] {ai_stand();};
|
||||
void() enf_stand7 =[ $stand7, enf_stand1 ] {ai_stand();};
|
||||
|
||||
void() enf_walk1 =[ $walk1 , enf_walk2 ]
|
||||
{
|
||||
if (random() < 0.2)
|
||||
sound (self, CHAN_VOICE, "enforcer/idle1.wav", 1, ATTN_IDLE);
|
||||
ai_walk(2);
|
||||
};
|
||||
void() enf_walk2 =[ $walk2 , enf_walk3 ] {ai_walk(4);};
|
||||
void() enf_walk3 =[ $walk3 , enf_walk4 ] {ai_walk(4);};
|
||||
void() enf_walk4 =[ $walk4 , enf_walk5 ] {ai_walk(3);};
|
||||
void() enf_walk5 =[ $walk5 , enf_walk6 ] {ai_walk(1);};
|
||||
void() enf_walk6 =[ $walk6 , enf_walk7 ] {ai_walk(2);};
|
||||
void() enf_walk7 =[ $walk7 , enf_walk8 ] {ai_walk(2);};
|
||||
void() enf_walk8 =[ $walk8 , enf_walk9 ] {ai_walk(1);};
|
||||
void() enf_walk9 =[ $walk9 , enf_walk10 ] {ai_walk(2);};
|
||||
void() enf_walk10 =[ $walk10, enf_walk11 ] {ai_walk(4);};
|
||||
void() enf_walk11 =[ $walk11, enf_walk12 ] {ai_walk(4);};
|
||||
void() enf_walk12 =[ $walk12, enf_walk13 ] {ai_walk(1);};
|
||||
void() enf_walk13 =[ $walk13, enf_walk14 ] {ai_walk(2);};
|
||||
void() enf_walk14 =[ $walk14, enf_walk15 ] {ai_walk(3);};
|
||||
void() enf_walk15 =[ $walk15, enf_walk16 ] {ai_walk(4);};
|
||||
void() enf_walk16 =[ $walk16, enf_walk1 ] {ai_walk(2);};
|
||||
|
||||
void() enf_run1 =[ $run1 , enf_run2 ]
|
||||
{
|
||||
if (random() < 0.2)
|
||||
sound (self, CHAN_VOICE, "enforcer/idle1.wav", 1, ATTN_IDLE);
|
||||
ai_run(18);
|
||||
};
|
||||
void() enf_run2 =[ $run2 , enf_run3 ] {ai_run(14);};
|
||||
void() enf_run3 =[ $run3 , enf_run4 ] {ai_run(7);};
|
||||
void() enf_run4 =[ $run4 , enf_run5 ] {ai_run(12);};
|
||||
void() enf_run5 =[ $run5 , enf_run6 ] {ai_run(14);};
|
||||
void() enf_run6 =[ $run6 , enf_run7 ] {ai_run(14);};
|
||||
void() enf_run7 =[ $run7 , enf_run8 ] {ai_run(7);};
|
||||
void() enf_run8 =[ $run8 , enf_run1 ] {ai_run(11);};
|
||||
|
||||
void() enf_atk1 =[ $attack1, enf_atk2 ] {ai_face();};
|
||||
void() enf_atk2 =[ $attack2, enf_atk3 ] {ai_face();};
|
||||
void() enf_atk3 =[ $attack3, enf_atk4 ] {ai_face();};
|
||||
void() enf_atk4 =[ $attack4, enf_atk5 ] {ai_face();};
|
||||
void() enf_atk5 =[ $attack5, enf_atk6 ] {ai_face();};
|
||||
void() enf_atk6 =[ $attack6, enf_atk7 ] {enforcer_fire();};
|
||||
void() enf_atk7 =[ $attack7, enf_atk8 ] {ai_face();};
|
||||
void() enf_atk8 =[ $attack8, enf_atk9 ] {ai_face();};
|
||||
void() enf_atk9 =[ $attack9, enf_atk10 ] {ai_face();};
|
||||
void() enf_atk10 =[ $attack10, enf_run1 ] {ai_face();if(visible(self.enemy)) if (FacingIdeal(30)) enf_atk4();};
|
||||
|
||||
void() enf_paina1 =[ $paina1, enf_paina2 ] {};
|
||||
void() enf_paina2 =[ $paina2, enf_paina3 ] {};
|
||||
void() enf_paina3 =[ $paina3, enf_paina4 ] {};
|
||||
void() enf_paina4 =[ $paina4, enf_run1 ] {};
|
||||
|
||||
void() enf_painb1 =[ $painb1, enf_painb2 ] {};
|
||||
void() enf_painb2 =[ $painb2, enf_painb3 ] {};
|
||||
void() enf_painb3 =[ $painb3, enf_painb4 ] {};
|
||||
void() enf_painb4 =[ $painb4, enf_painb5 ] {};
|
||||
void() enf_painb5 =[ $painb5, enf_run1 ] {};
|
||||
|
||||
void() enf_painc1 =[ $painc1, enf_painc2 ] {};
|
||||
void() enf_painc2 =[ $painc2, enf_painc3 ] {};
|
||||
void() enf_painc3 =[ $painc3, enf_painc4 ] {};
|
||||
void() enf_painc4 =[ $painc4, enf_painc5 ] {};
|
||||
void() enf_painc5 =[ $painc5, enf_painc6 ] {};
|
||||
void() enf_painc6 =[ $painc6, enf_painc7 ] {};
|
||||
void() enf_painc7 =[ $painc7, enf_painc8 ] {};
|
||||
void() enf_painc8 =[ $painc8, enf_run1 ] {};
|
||||
|
||||
void() enf_paind1 =[ $paind1, enf_paind2 ] {};
|
||||
void() enf_paind2 =[ $paind2, enf_paind3 ] {};
|
||||
void() enf_paind3 =[ $paind3, enf_paind4 ] {};
|
||||
void() enf_paind4 =[ $paind4, enf_paind5 ] {ai_painforward(2);};
|
||||
void() enf_paind5 =[ $paind5, enf_paind6 ] {ai_painforward(1);};
|
||||
void() enf_paind6 =[ $paind6, enf_paind7 ] {};
|
||||
void() enf_paind7 =[ $paind7, enf_paind8 ] {};
|
||||
void() enf_paind8 =[ $paind8, enf_paind9 ] {};
|
||||
void() enf_paind9 =[ $paind9, enf_paind10 ] {};
|
||||
void() enf_paind10 =[ $paind10, enf_paind11 ] {};
|
||||
void() enf_paind11 =[ $paind11, enf_paind12 ] {ai_painforward(1);};
|
||||
void() enf_paind12 =[ $paind12, enf_paind13 ] {ai_painforward(1);};
|
||||
void() enf_paind13 =[ $paind13, enf_paind14 ] {ai_painforward(1);};
|
||||
void() enf_paind14 =[ $paind14, enf_paind15 ] {};
|
||||
void() enf_paind15 =[ $paind15, enf_paind16 ] {};
|
||||
void() enf_paind16 =[ $paind16, enf_paind17 ] {ai_pain(1);};
|
||||
void() enf_paind17 =[ $paind17, enf_paind18 ] {ai_pain(1);};
|
||||
void() enf_paind18 =[ $paind18, enf_paind19 ] {};
|
||||
void() enf_paind19 =[ $paind19, enf_run1 ] {};
|
||||
|
||||
void(entity attacker, float damage) enf_pain =
|
||||
{
|
||||
if (self.pain_finished > time)
|
||||
return;
|
||||
|
||||
float r = random();
|
||||
if (r < 0.5)
|
||||
sound (self, CHAN_VOICE, "enforcer/pain1.wav", 1, ATTN_NORM);
|
||||
else
|
||||
sound (self, CHAN_VOICE, "enforcer/pain2.wav", 1, ATTN_NORM);
|
||||
|
||||
r = random();
|
||||
if (r < 0.2)
|
||||
{
|
||||
self.pain_finished = time + 1;
|
||||
enf_paina1 ();
|
||||
}
|
||||
else if (r < 0.4)
|
||||
{
|
||||
self.pain_finished = time + 1;
|
||||
enf_painb1 ();
|
||||
}
|
||||
else if (r < 0.7)
|
||||
{
|
||||
self.pain_finished = time + 1;
|
||||
enf_painc1 ();
|
||||
}
|
||||
else
|
||||
{
|
||||
self.pain_finished = time + 2;
|
||||
enf_paind1 ();
|
||||
}
|
||||
};
|
||||
|
||||
void() enf_die1 =[ $death1, enf_die2 ] {};
|
||||
void() enf_die2 =[ $death2, enf_die3 ] {};
|
||||
void() enf_die3 =[ $death3, enf_die4 ]
|
||||
{self.solid = SOLID_NOT;self.ammo_cells = 5;DropBackpack();};
|
||||
void() enf_die4 =[ $death4, enf_die5 ] {ai_forward(14);};
|
||||
void() enf_die5 =[ $death5, enf_die6 ] {ai_forward(2);};
|
||||
void() enf_die6 =[ $death6, enf_die7 ] {};
|
||||
void() enf_die7 =[ $death7, enf_die8 ] {};
|
||||
void() enf_die8 =[ $death8, enf_die9 ] {};
|
||||
void() enf_die9 =[ $death9, enf_die10 ] {ai_forward(3);};
|
||||
void() enf_die10 =[ $death10, enf_die11 ] {ai_forward(5);};
|
||||
void() enf_die11 =[ $death11, enf_die12 ] {ai_forward(5);};
|
||||
void() enf_die12 =[ $death12, enf_die13 ] {ai_forward(5);};
|
||||
void() enf_die13 =[ $death13, enf_die14 ] {};
|
||||
void() enf_die14 =[ $death14, enf_die14 ] {};
|
||||
|
||||
void() enf_fdie1 =[ $fdeath1, enf_fdie2 ] {};
|
||||
void() enf_fdie2 =[ $fdeath2, enf_fdie3 ] {};
|
||||
void() enf_fdie3 =[ $fdeath3, enf_fdie4 ] {DropBackpack();};
|
||||
void() enf_fdie4 =[ $fdeath4, enf_fdie5 ] {};
|
||||
void() enf_fdie5 =[ $fdeath5, enf_fdie6 ] {};
|
||||
void() enf_fdie6 =[ $fdeath6, enf_fdie7 ] {};
|
||||
void() enf_fdie7 =[ $fdeath7, enf_fdie8 ] {};
|
||||
void() enf_fdie8 =[ $fdeath8, enf_fdie9 ] {};
|
||||
void() enf_fdie9 =[ $fdeath9, enf_fdie10 ] {};
|
||||
void() enf_fdie10 =[ $fdeath10, enf_fdie11 ] {};
|
||||
void() enf_fdie11 =[ $fdeath11, enf_fdie11 ] {};
|
||||
|
||||
|
||||
void(entity inflictor, entity attacker) enf_die =
|
||||
{
|
||||
// check for gib
|
||||
if (self.health < -35)
|
||||
{
|
||||
SpawnGib("progs/gib1.mdl");
|
||||
SpawnGib("progs/gib2.mdl");
|
||||
SpawnGib("progs/gib3.mdl");
|
||||
SpawnGib("progs/gib4.mdl");
|
||||
SpawnGib("progs/gib5.mdl");
|
||||
SpawnGib("progs/blood.mdl");
|
||||
SpawnGib("progs/blood.mdl");
|
||||
BecomeGibs();
|
||||
return;
|
||||
}
|
||||
|
||||
// regular death
|
||||
sound (self, CHAN_VOICE, "enforcer/death1.wav", 1, ATTN_NORM);
|
||||
self.solid = SOLID_NOT;
|
||||
if (random() > 0.5)
|
||||
enf_die1 ();
|
||||
else
|
||||
enf_fdie1 ();
|
||||
};
|
||||
|
||||
/*QUAKED monster_enforcer (1 0 0) (-16 -16 -24) (16 16 40) AMBUSH
|
||||
{
|
||||
model ("progs/enforcer.mdl");
|
||||
}
|
||||
Enforcer.
|
||||
Grunt, Mark Two. Grunts who are surlier and beefier than the rest get outfitted in combat armor and built-in blasters.
|
||||
*/
|
||||
void() monster_enforcer =
|
||||
{
|
||||
if (deathmatch)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
precache_model2 ("progs/enforcer.mdl");
|
||||
precache_model2 ("progs/h_mega.mdl");
|
||||
precache_model2 ("progs/laser.mdl");
|
||||
|
||||
precache_sound2 ("enforcer/death1.wav");
|
||||
precache_sound2 ("enforcer/enfire.wav");
|
||||
precache_sound2 ("enforcer/enfstop.wav");
|
||||
precache_sound2 ("enforcer/idle1.wav");
|
||||
precache_sound2 ("enforcer/pain1.wav");
|
||||
precache_sound2 ("enforcer/pain2.wav");
|
||||
precache_sound2 ("enforcer/sight1.wav");
|
||||
precache_sound2 ("enforcer/sight2.wav");
|
||||
precache_sound2 ("enforcer/sight3.wav");
|
||||
precache_sound2 ("enforcer/sight4.wav");
|
||||
|
||||
self.th_stand = enf_stand1;
|
||||
self.th_walk = enf_walk1;
|
||||
self.th_run = enf_run1;
|
||||
self.th_pain = enf_pain;
|
||||
self.th_die = enf_die;
|
||||
self.th_missile = enf_atk1;
|
||||
|
||||
self.ammo_cells = 5;
|
||||
|
||||
monster_start("progs/enforcer.mdl", "progs/h_mega.mdl", 80, 0, '-16 -16 -24', '16 16 40');
|
||||
};
|
||||
181
mod_slipgate/source/server/monsters/fish.qc
Normal file
181
mod_slipgate/source/server/monsters/fish.qc
Normal file
@@ -0,0 +1,181 @@
|
||||
$cd id1/models/fish
|
||||
$origin 0 0 24
|
||||
$base base
|
||||
$skin skin
|
||||
|
||||
$frame attack1 attack2 attack3 attack4 attack5 attack6
|
||||
$frame attack7 attack8 attack9 attack10 attack11 attack12 attack13
|
||||
$frame attack14 attack15 attack16 attack17 attack18
|
||||
|
||||
$frame death1 death2 death3 death4 death5 death6 death7
|
||||
$frame death8 death9 death10 death11 death12 death13 death14 death15
|
||||
$frame death16 death17 death18 death19 death20 death21
|
||||
|
||||
$frame swim1 swim2 swim3 swim4 swim5 swim6 swim7 swim8
|
||||
$frame swim9 swim10 swim11 swim12 swim13 swim14 swim15 swim16 swim17
|
||||
$frame swim18
|
||||
|
||||
$frame pain1 pain2 pain3 pain4 pain5 pain6 pain7 pain8
|
||||
$frame pain9
|
||||
|
||||
void() f_stand1 =[ $swim1, f_stand2 ] {ai_stand();};
|
||||
void() f_stand2 =[ $swim2, f_stand3 ] {ai_stand();};
|
||||
void() f_stand3 =[ $swim3, f_stand4 ] {ai_stand();};
|
||||
void() f_stand4 =[ $swim4, f_stand5 ] {ai_stand();};
|
||||
void() f_stand5 =[ $swim5, f_stand6 ] {ai_stand();};
|
||||
void() f_stand6 =[ $swim6, f_stand7 ] {ai_stand();};
|
||||
void() f_stand7 =[ $swim7, f_stand8 ] {ai_stand();};
|
||||
void() f_stand8 =[ $swim8, f_stand9 ] {ai_stand();};
|
||||
void() f_stand9 =[ $swim9, f_stand10 ] {ai_stand();};
|
||||
void() f_stand10 =[ $swim10, f_stand11 ] {ai_stand();};
|
||||
void() f_stand11 =[ $swim11, f_stand12 ] {ai_stand();};
|
||||
void() f_stand12 =[ $swim12, f_stand13 ] {ai_stand();};
|
||||
void() f_stand13 =[ $swim13, f_stand14 ] {ai_stand();};
|
||||
void() f_stand14 =[ $swim14, f_stand15 ] {ai_stand();};
|
||||
void() f_stand15 =[ $swim15, f_stand16 ] {ai_stand();};
|
||||
void() f_stand16 =[ $swim16, f_stand17 ] {ai_stand();};
|
||||
void() f_stand17 =[ $swim17, f_stand18 ] {ai_stand();};
|
||||
void() f_stand18 =[ $swim18, f_stand1 ] {ai_stand();};
|
||||
|
||||
void() f_walk1 =[ $swim1, f_walk2 ] {ai_walk(8);};
|
||||
void() f_walk2 =[ $swim2, f_walk3 ] {ai_walk(8);};
|
||||
void() f_walk3 =[ $swim3, f_walk4 ] {ai_walk(8);};
|
||||
void() f_walk4 =[ $swim4, f_walk5 ] {ai_walk(8);};
|
||||
void() f_walk5 =[ $swim5, f_walk6 ] {ai_walk(8);};
|
||||
void() f_walk6 =[ $swim6, f_walk7 ] {ai_walk(8);};
|
||||
void() f_walk7 =[ $swim7, f_walk8 ] {ai_walk(8);};
|
||||
void() f_walk8 =[ $swim8, f_walk9 ] {ai_walk(8);};
|
||||
void() f_walk9 =[ $swim9, f_walk10 ] {ai_walk(8);};
|
||||
void() f_walk10 =[ $swim10, f_walk11 ] {ai_walk(8);};
|
||||
void() f_walk11 =[ $swim11, f_walk12 ] {ai_walk(8);};
|
||||
void() f_walk12 =[ $swim12, f_walk13 ] {ai_walk(8);};
|
||||
void() f_walk13 =[ $swim13, f_walk14 ] {ai_walk(8);};
|
||||
void() f_walk14 =[ $swim14, f_walk15 ] {ai_walk(8);};
|
||||
void() f_walk15 =[ $swim15, f_walk16 ] {ai_walk(8);};
|
||||
void() f_walk16 =[ $swim16, f_walk17 ] {ai_walk(8);};
|
||||
void() f_walk17 =[ $swim17, f_walk18 ] {ai_walk(8);};
|
||||
void() f_walk18 =[ $swim18, f_walk1 ] {ai_walk(8);};
|
||||
|
||||
void() f_run1 =[ $swim1, f_run2 ] {ai_run(12);
|
||||
if (random() < 0.5)
|
||||
sound (self, CHAN_VOICE, "fish/idle.wav", 1, ATTN_NORM);
|
||||
};
|
||||
void() f_run2 =[ $swim3, f_run3 ] {ai_run(12);};
|
||||
void() f_run3 =[ $swim5, f_run4 ] {ai_run(12);};
|
||||
void() f_run4 =[ $swim7, f_run5 ] {ai_run(12);};
|
||||
void() f_run5 =[ $swim9, f_run6 ] {ai_run(12);};
|
||||
void() f_run6 =[ $swim11, f_run7 ] {ai_run(12);};
|
||||
void() f_run7 =[ $swim13, f_run8 ] {ai_run(12);};
|
||||
void() f_run8 =[ $swim15, f_run9 ] {ai_run(12);};
|
||||
void() f_run9 =[ $swim17, f_run1 ] {ai_run(12);};
|
||||
|
||||
void() fish_melee =
|
||||
{
|
||||
local vector delta;
|
||||
local float ldmg;
|
||||
|
||||
if (!self.enemy)
|
||||
return; // removed before stroke
|
||||
|
||||
delta = self.enemy.origin - self.origin;
|
||||
|
||||
if (vlen(delta) > 60)
|
||||
return;
|
||||
|
||||
sound (self, CHAN_VOICE, "fish/bite.wav", 1, ATTN_NORM);
|
||||
ldmg = (random() + random()) * 3;
|
||||
Damage (self.enemy, self, self, ldmg);
|
||||
};
|
||||
|
||||
void() f_attack1 =[ $attack1, f_attack2 ] {ai_charge(10);};
|
||||
void() f_attack2 =[ $attack2, f_attack3 ] {ai_charge(10);};
|
||||
void() f_attack3 =[ $attack3, f_attack4 ] {fish_melee();};
|
||||
void() f_attack4 =[ $attack4, f_attack5 ] {ai_charge(10);};
|
||||
void() f_attack5 =[ $attack5, f_attack6 ] {ai_charge(10);};
|
||||
void() f_attack6 =[ $attack6, f_attack7 ] {ai_charge(10);};
|
||||
void() f_attack7 =[ $attack7, f_attack8 ] {ai_charge(10);};
|
||||
void() f_attack8 =[ $attack8, f_attack9 ] {ai_charge(10);};
|
||||
void() f_attack9 =[ $attack9, f_attack10] {fish_melee();};
|
||||
void() f_attack10 =[ $attack10, f_attack11] {ai_charge(10);};
|
||||
void() f_attack11 =[ $attack11, f_attack12] {ai_charge(10);};
|
||||
void() f_attack12 =[ $attack12, f_attack13] {ai_charge(10);};
|
||||
void() f_attack13 =[ $attack13, f_attack14] {ai_charge(10);};
|
||||
void() f_attack14 =[ $attack14, f_attack15] {ai_charge(10);};
|
||||
void() f_attack15 =[ $attack15, f_attack16] {fish_melee();};
|
||||
void() f_attack16 =[ $attack16, f_attack17] {ai_charge(10);};
|
||||
void() f_attack17 =[ $attack17, f_attack18] {ai_charge(10);};
|
||||
void() f_attack18 =[ $attack18, f_run1 ] {ai_charge(10);};
|
||||
|
||||
void() f_death1 =[ $death1, f_death2 ] {sound (self, CHAN_VOICE, "fish/death.wav", 1, ATTN_NORM);};
|
||||
void() f_death2 =[ $death2, f_death3 ] {};
|
||||
void() f_death3 =[ $death3, f_death4 ] {};
|
||||
void() f_death4 =[ $death4, f_death5 ] {};
|
||||
void() f_death5 =[ $death5, f_death6 ] {};
|
||||
void() f_death6 =[ $death6, f_death7 ] {};
|
||||
void() f_death7 =[ $death7, f_death8 ] {};
|
||||
void() f_death8 =[ $death8, f_death9 ] {};
|
||||
void() f_death9 =[ $death9, f_death10 ] {};
|
||||
void() f_death10 =[ $death10, f_death11 ] {};
|
||||
void() f_death11 =[ $death11, f_death12 ] {};
|
||||
void() f_death12 =[ $death12, f_death13 ] {};
|
||||
void() f_death13 =[ $death13, f_death14 ] {};
|
||||
void() f_death14 =[ $death14, f_death15 ] {};
|
||||
void() f_death15 =[ $death15, f_death16 ] {};
|
||||
void() f_death16 =[ $death16, f_death17 ] {};
|
||||
void() f_death17 =[ $death17, f_death18 ] {};
|
||||
void() f_death18 =[ $death18, f_death19 ] {};
|
||||
void() f_death19 =[ $death19, f_death20 ] {};
|
||||
void() f_death20 =[ $death20, f_death21 ] {};
|
||||
void() f_death21 =[ $death21, f_death21 ] {};
|
||||
|
||||
void(entity inflictor, entity attacker) f_death =
|
||||
{
|
||||
self.solid = SOLID_NOT;
|
||||
f_death1();
|
||||
};
|
||||
|
||||
void() f_pain1 =[ $pain1, f_pain2 ] {};
|
||||
void() f_pain2 =[ $pain2, f_pain3 ] {ai_pain(6);};
|
||||
void() f_pain3 =[ $pain3, f_pain4 ] {ai_pain(6);};
|
||||
void() f_pain4 =[ $pain4, f_pain5 ] {ai_pain(6);};
|
||||
void() f_pain5 =[ $pain5, f_pain6 ] {ai_pain(6);};
|
||||
void() f_pain6 =[ $pain6, f_pain7 ] {ai_pain(6);};
|
||||
void() f_pain7 =[ $pain7, f_pain8 ] {ai_pain(6);};
|
||||
void() f_pain8 =[ $pain8, f_pain9 ] {ai_pain(6);};
|
||||
void() f_pain9 =[ $pain9, f_run1 ] {ai_pain(6);};
|
||||
|
||||
void(entity attacker, float damage) fish_pain =
|
||||
{
|
||||
|
||||
// fish allways do pain frames
|
||||
f_pain1 ();
|
||||
};
|
||||
|
||||
/*QUAKED monster_fish (1 0 0) (-16 -16 -24) (16 16 24) Ambush
|
||||
{
|
||||
model ("progs/fish.mdl");
|
||||
}
|
||||
Rotfish.
|
||||
*/
|
||||
void() monster_fish =
|
||||
{
|
||||
if (deathmatch)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
precache_model2 ("progs/fish.mdl");
|
||||
precache_sound2 ("fish/death.wav");
|
||||
precache_sound2 ("fish/bite.wav");
|
||||
precache_sound2 ("fish/idle.wav");
|
||||
|
||||
self.th_stand = f_stand1;
|
||||
self.th_walk = f_walk1;
|
||||
self.th_run = f_run1;
|
||||
self.th_die = f_death;
|
||||
self.th_pain = fish_pain;
|
||||
self.th_melee = f_attack1;
|
||||
|
||||
monster_start("progs/fish.mdl", "progs/gib3.mdl", 25, FL_SWIM, '-16 -16 -24', '16 16 24');
|
||||
};
|
||||
|
||||
426
mod_slipgate/source/server/monsters/hknight.qc
Normal file
426
mod_slipgate/source/server/monsters/hknight.qc
Normal file
@@ -0,0 +1,426 @@
|
||||
$frame stand1 stand2 stand3 stand4 stand5 stand6 stand7 stand8 stand9
|
||||
|
||||
$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8 walk9
|
||||
$frame walk10 walk11 walk12 walk13 walk14 walk15 walk16 walk17
|
||||
$frame walk18 walk19 walk20
|
||||
|
||||
$frame run1 run2 run3 run4 run5 run6 run7 run8
|
||||
|
||||
$frame pain1 pain2 pain3 pain4 pain5
|
||||
|
||||
$frame death1 death2 death3 death4 death5 death6 death7 death8
|
||||
$frame death9 death10 death11 death12
|
||||
|
||||
$frame deathb1 deathb2 deathb3 deathb4 deathb5 deathb6 deathb7 deathb8
|
||||
$frame deathb9
|
||||
|
||||
$frame char_a1 char_a2 char_a3 char_a4 char_a5 char_a6 char_a7 char_a8
|
||||
$frame char_a9 char_a10 char_a11 char_a12 char_a13 char_a14 char_a15 char_a16
|
||||
|
||||
$frame magica1 magica2 magica3 magica4 magica5 magica6 magica7 magica8
|
||||
$frame magica9 magica10 magica11 magica12 magica13 magica14
|
||||
|
||||
$frame magicb1 magicb2 magicb3 magicb4 magicb5 magicb6 magicb7 magicb8
|
||||
$frame magicb9 magicb10 magicb11 magicb12 magicb13
|
||||
|
||||
$frame char_b1 char_b2 char_b3 char_b4 char_b5 char_b6
|
||||
|
||||
$frame slice1 slice2 slice3 slice4 slice5 slice6 slice7 slice8 slice9 slice10
|
||||
|
||||
$frame smash1 smash2 smash3 smash4 smash5 smash6 smash7 smash8 smash9 smash10
|
||||
$frame smash11
|
||||
|
||||
$frame w_attack1 w_attack2 w_attack3 w_attack4 w_attack5 w_attack6 w_attack7
|
||||
$frame w_attack8 w_attack9 w_attack10 w_attack11 w_attack12 w_attack13 w_attack14
|
||||
$frame w_attack15 w_attack16 w_attack17 w_attack18 w_attack19 w_attack20
|
||||
$frame w_attack21 w_attack22
|
||||
|
||||
$frame magicc1 magicc2 magicc3 magicc4 magicc5 magicc6 magicc7 magicc8
|
||||
$frame magicc9 magicc10 magicc11
|
||||
|
||||
|
||||
void() hknight_char_a1;
|
||||
void() hknight_run1;
|
||||
void() hk_idle_sound;
|
||||
|
||||
void(float offset) hknight_shot =
|
||||
{
|
||||
local vector offang;
|
||||
local vector org, vec;
|
||||
|
||||
offang = vectoangles (self.enemy.origin - self.origin);
|
||||
offang_y = offang_y + offset * 6;
|
||||
|
||||
makevectors (offang);
|
||||
|
||||
org = self.origin + self.mins + self.size*0.5 + v_forward * 20;
|
||||
|
||||
// set missile speed
|
||||
vec = normalize (v_forward);
|
||||
vec_z = 0 - vec_z + (random() - 0.5)*0.1;
|
||||
|
||||
launch_spike (org, vec);
|
||||
newmis.classname = "knightspike";
|
||||
setmodel (newmis, "progs/k_spike.mdl");
|
||||
setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
|
||||
newmis.velocity = vec*300;
|
||||
sound (self, CHAN_WEAPON, "hknight/attack1.wav", 1, ATTN_NORM);
|
||||
};
|
||||
|
||||
void() CheckForCharge =
|
||||
{
|
||||
// check for mad charge
|
||||
if (!enemy_vis)
|
||||
return;
|
||||
if (time < self.attack_finished)
|
||||
return;
|
||||
if ( fabs(self.origin_z - self.enemy.origin_z) > 20)
|
||||
return; // too much height change
|
||||
if ( vlen (self.origin - self.enemy.origin) < 80)
|
||||
return; // use regular attack
|
||||
|
||||
// charge
|
||||
SUB_AttackFinished (2);
|
||||
hknight_char_a1 ();
|
||||
|
||||
};
|
||||
|
||||
void() CheckContinueCharge =
|
||||
{
|
||||
if (time > self.attack_finished)
|
||||
{
|
||||
SUB_AttackFinished (3);
|
||||
hknight_run1 ();
|
||||
return; // done charging
|
||||
}
|
||||
if (random() > 0.5)
|
||||
sound (self, CHAN_WEAPON, "knight/sword2.wav", 1, ATTN_NORM);
|
||||
else
|
||||
sound (self, CHAN_WEAPON, "knight/sword1.wav", 1, ATTN_NORM);
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void() hknight_stand1 =[ $stand1, hknight_stand2 ] {ai_stand();};
|
||||
void() hknight_stand2 =[ $stand2, hknight_stand3 ] {ai_stand();};
|
||||
void() hknight_stand3 =[ $stand3, hknight_stand4 ] {ai_stand();};
|
||||
void() hknight_stand4 =[ $stand4, hknight_stand5 ] {ai_stand();};
|
||||
void() hknight_stand5 =[ $stand5, hknight_stand6 ] {ai_stand();};
|
||||
void() hknight_stand6 =[ $stand6, hknight_stand7 ] {ai_stand();};
|
||||
void() hknight_stand7 =[ $stand7, hknight_stand8 ] {ai_stand();};
|
||||
void() hknight_stand8 =[ $stand8, hknight_stand9 ] {ai_stand();};
|
||||
void() hknight_stand9 =[ $stand9, hknight_stand1 ] {ai_stand();};
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void() hknight_walk1 =[ $walk1, hknight_walk2 ] {
|
||||
hk_idle_sound();
|
||||
ai_walk(2);};
|
||||
void() hknight_walk2 =[ $walk2, hknight_walk3 ] {ai_walk(5);};
|
||||
void() hknight_walk3 =[ $walk3, hknight_walk4 ] {ai_walk(5);};
|
||||
void() hknight_walk4 =[ $walk4, hknight_walk5 ] {ai_walk(4);};
|
||||
void() hknight_walk5 =[ $walk5, hknight_walk6 ] {ai_walk(4);};
|
||||
void() hknight_walk6 =[ $walk6, hknight_walk7 ] {ai_walk(2);};
|
||||
void() hknight_walk7 =[ $walk7, hknight_walk8 ] {ai_walk(2);};
|
||||
void() hknight_walk8 =[ $walk8, hknight_walk9 ] {ai_walk(3);};
|
||||
void() hknight_walk9 =[ $walk9, hknight_walk10 ] {ai_walk(3);};
|
||||
void() hknight_walk10 =[ $walk10, hknight_walk11 ] {ai_walk(4);};
|
||||
void() hknight_walk11 =[ $walk11, hknight_walk12 ] {ai_walk(3);};
|
||||
void() hknight_walk12 =[ $walk12, hknight_walk13 ] {ai_walk(4);};
|
||||
void() hknight_walk13 =[ $walk13, hknight_walk14 ] {ai_walk(6);};
|
||||
void() hknight_walk14 =[ $walk14, hknight_walk15 ] {ai_walk(2);};
|
||||
void() hknight_walk15 =[ $walk15, hknight_walk16 ] {ai_walk(2);};
|
||||
void() hknight_walk16 =[ $walk16, hknight_walk17 ] {ai_walk(4);};
|
||||
void() hknight_walk17 =[ $walk17, hknight_walk18 ] {ai_walk(3);};
|
||||
void() hknight_walk18 =[ $walk18, hknight_walk19 ] {ai_walk(3);};
|
||||
void() hknight_walk19 =[ $walk19, hknight_walk20 ] {ai_walk(3);};
|
||||
void() hknight_walk20 =[ $walk20, hknight_walk1 ] {ai_walk(2);};
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void() hknight_run1 =[ $run1, hknight_run2 ] {
|
||||
hk_idle_sound();
|
||||
ai_run (20); CheckForCharge (); };
|
||||
void() hknight_run2 =[ $run2, hknight_run3 ] {ai_run(25);};
|
||||
void() hknight_run3 =[ $run3, hknight_run4 ] {ai_run(18);};
|
||||
void() hknight_run4 =[ $run4, hknight_run5 ] {ai_run(16);};
|
||||
void() hknight_run5 =[ $run5, hknight_run6 ] {ai_run(14);};
|
||||
void() hknight_run6 =[ $run6, hknight_run7 ] {ai_run(25);};
|
||||
void() hknight_run7 =[ $run7, hknight_run8 ] {ai_run(21);};
|
||||
void() hknight_run8 =[ $run8, hknight_run1 ] {ai_run(13);};
|
||||
|
||||
//============================================================================
|
||||
|
||||
void() hknight_pain1 =[ $pain1, hknight_pain2 ] {sound (self, CHAN_VOICE, "hknight/pain1.wav", 1, ATTN_NORM);};
|
||||
void() hknight_pain2 =[ $pain2, hknight_pain3 ] {};
|
||||
void() hknight_pain3 =[ $pain3, hknight_pain4 ] {};
|
||||
void() hknight_pain4 =[ $pain4, hknight_pain5 ] {};
|
||||
void() hknight_pain5 =[ $pain5, hknight_run1 ] {};
|
||||
|
||||
//============================================================================
|
||||
|
||||
void() hknight_die1 =[ $death1, hknight_die2 ] {ai_forward(10);};
|
||||
void() hknight_die2 =[ $death2, hknight_die3 ] {ai_forward(8);};
|
||||
void() hknight_die3 =[ $death3, hknight_die4 ] {ai_forward(7);};
|
||||
void() hknight_die4 =[ $death4, hknight_die5 ] {};
|
||||
void() hknight_die5 =[ $death5, hknight_die6 ] {};
|
||||
void() hknight_die6 =[ $death6, hknight_die7 ] {};
|
||||
void() hknight_die7 =[ $death7, hknight_die8 ] {};
|
||||
void() hknight_die8 =[ $death8, hknight_die9 ] {ai_forward(10);};
|
||||
void() hknight_die9 =[ $death9, hknight_die10 ] {ai_forward(11);};
|
||||
void() hknight_die10 =[ $death10, hknight_die11 ] {};
|
||||
void() hknight_die11 =[ $death11, hknight_die12 ] {};
|
||||
void() hknight_die12 =[ $death12, hknight_die12 ] {};
|
||||
|
||||
void() hknight_dieb1 =[ $deathb1, hknight_dieb2 ] {};
|
||||
void() hknight_dieb2 =[ $deathb2, hknight_dieb3 ] {};
|
||||
void() hknight_dieb3 =[ $deathb3, hknight_dieb4 ] {};
|
||||
void() hknight_dieb4 =[ $deathb4, hknight_dieb5 ] {};
|
||||
void() hknight_dieb5 =[ $deathb5, hknight_dieb6 ] {};
|
||||
void() hknight_dieb6 =[ $deathb6, hknight_dieb7 ] {};
|
||||
void() hknight_dieb7 =[ $deathb7, hknight_dieb8 ] {};
|
||||
void() hknight_dieb8 =[ $deathb8, hknight_dieb9 ] {};
|
||||
void() hknight_dieb9 =[ $deathb9, hknight_dieb9 ] {};
|
||||
|
||||
void(entity inflictor, entity attacker) hknight_die =
|
||||
{
|
||||
// check for gib
|
||||
if (self.health < -40)
|
||||
{
|
||||
SpawnGib("progs/gib1.mdl");
|
||||
SpawnGib("progs/gib2.mdl");
|
||||
SpawnGib("progs/gib3.mdl");
|
||||
SpawnGib("progs/gib4.mdl");
|
||||
SpawnGib("progs/gib5.mdl");
|
||||
SpawnGib("progs/blood.mdl");
|
||||
SpawnGib("progs/blood.mdl");
|
||||
BecomeGibs();
|
||||
return;
|
||||
}
|
||||
|
||||
// regular death
|
||||
sound (self, CHAN_VOICE, "hknight/death1.wav", 1, ATTN_NORM);
|
||||
self.solid = SOLID_NOT;
|
||||
if (random() > 0.5)
|
||||
hknight_die1();
|
||||
else
|
||||
hknight_dieb1();
|
||||
};
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
void() hknight_magica1 =[ $magica1, hknight_magica2 ] {ai_face();};
|
||||
void() hknight_magica2 =[ $magica2, hknight_magica3 ] {ai_face();};
|
||||
void() hknight_magica3 =[ $magica3, hknight_magica4 ] {ai_face();};
|
||||
void() hknight_magica4 =[ $magica4, hknight_magica5 ] {ai_face();};
|
||||
void() hknight_magica5 =[ $magica5, hknight_magica6 ] {ai_face();};
|
||||
void() hknight_magica6 =[ $magica6, hknight_magica7 ] {ai_face();};
|
||||
void() hknight_magica7 =[ $magica7, hknight_magica8 ] {hknight_shot(-2);};
|
||||
void() hknight_magica8 =[ $magica8, hknight_magica9 ] {hknight_shot(-1);};
|
||||
void() hknight_magica9 =[ $magica9, hknight_magica10] {hknight_shot(0);};
|
||||
void() hknight_magica10 =[ $magica10, hknight_magica11] {hknight_shot(1);};
|
||||
void() hknight_magica11 =[ $magica11, hknight_magica12] {hknight_shot(2);};
|
||||
void() hknight_magica12 =[ $magica12, hknight_magica13] {hknight_shot(3);};
|
||||
void() hknight_magica13 =[ $magica13, hknight_magica14] {ai_face();};
|
||||
void() hknight_magica14 =[ $magica14, hknight_run1 ] {ai_face();};
|
||||
|
||||
//============================================================================
|
||||
|
||||
void() hknight_magicb1 =[ $magicb1, hknight_magicb2 ] {ai_face();};
|
||||
void() hknight_magicb2 =[ $magicb2, hknight_magicb3 ] {ai_face();};
|
||||
void() hknight_magicb3 =[ $magicb3, hknight_magicb4 ] {ai_face();};
|
||||
void() hknight_magicb4 =[ $magicb4, hknight_magicb5 ] {ai_face();};
|
||||
void() hknight_magicb5 =[ $magicb5, hknight_magicb6 ] {ai_face();};
|
||||
void() hknight_magicb6 =[ $magicb6, hknight_magicb7 ] {ai_face();};
|
||||
void() hknight_magicb7 =[ $magicb7, hknight_magicb8 ] {hknight_shot(-2);};
|
||||
void() hknight_magicb8 =[ $magicb8, hknight_magicb9 ] {hknight_shot(-1);};
|
||||
void() hknight_magicb9 =[ $magicb9, hknight_magicb10] {hknight_shot(0);};
|
||||
void() hknight_magicb10 =[ $magicb10, hknight_magicb11] {hknight_shot(1);};
|
||||
void() hknight_magicb11 =[ $magicb11, hknight_magicb12] {hknight_shot(2);};
|
||||
void() hknight_magicb12 =[ $magicb12, hknight_magicb13] {hknight_shot(3);};
|
||||
void() hknight_magicb13 =[ $magicb13, hknight_run1] {ai_face();};
|
||||
|
||||
//============================================================================
|
||||
|
||||
void() hknight_magicc1 =[ $magicc1, hknight_magicc2 ] {ai_face();};
|
||||
void() hknight_magicc2 =[ $magicc2, hknight_magicc3 ] {ai_face();};
|
||||
void() hknight_magicc3 =[ $magicc3, hknight_magicc4 ] {ai_face();};
|
||||
void() hknight_magicc4 =[ $magicc4, hknight_magicc5 ] {ai_face();};
|
||||
void() hknight_magicc5 =[ $magicc5, hknight_magicc6 ] {ai_face();};
|
||||
void() hknight_magicc6 =[ $magicc6, hknight_magicc7 ] {hknight_shot(-2);};
|
||||
void() hknight_magicc7 =[ $magicc7, hknight_magicc8 ] {hknight_shot(-1);};
|
||||
void() hknight_magicc8 =[ $magicc8, hknight_magicc9 ] {hknight_shot(0);};
|
||||
void() hknight_magicc9 =[ $magicc9, hknight_magicc10] {hknight_shot(1);};
|
||||
void() hknight_magicc10 =[ $magicc10, hknight_magicc11] {hknight_shot(2);};
|
||||
void() hknight_magicc11 =[ $magicc11, hknight_run1] {hknight_shot(3);};
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void() hknight_char_a1 =[ $char_a1, hknight_char_a2 ] {ai_charge(20);};
|
||||
void() hknight_char_a2 =[ $char_a2, hknight_char_a3 ] {ai_charge(25);};
|
||||
void() hknight_char_a3 =[ $char_a3, hknight_char_a4 ] {ai_charge(18);};
|
||||
void() hknight_char_a4 =[ $char_a4, hknight_char_a5 ] {ai_charge(16);};
|
||||
void() hknight_char_a5 =[ $char_a5, hknight_char_a6 ] {ai_charge(14);};
|
||||
void() hknight_char_a6 =[ $char_a6, hknight_char_a7 ] {ai_charge(20); ai_melee();};
|
||||
void() hknight_char_a7 =[ $char_a7, hknight_char_a8 ] {ai_charge(21); ai_melee();};
|
||||
void() hknight_char_a8 =[ $char_a8, hknight_char_a9 ] {ai_charge(13); ai_melee();};
|
||||
void() hknight_char_a9 =[ $char_a9, hknight_char_a10 ] {ai_charge(20); ai_melee();};
|
||||
void() hknight_char_a10=[ $char_a10, hknight_char_a11 ] {ai_charge(20); ai_melee();};
|
||||
void() hknight_char_a11=[ $char_a11, hknight_char_a12 ] {ai_charge(18); ai_melee();};
|
||||
void() hknight_char_a12=[ $char_a12, hknight_char_a13 ] {ai_charge(16);};
|
||||
void() hknight_char_a13=[ $char_a13, hknight_char_a14 ] {ai_charge(14);};
|
||||
void() hknight_char_a14=[ $char_a14, hknight_char_a15 ] {ai_charge(25);};
|
||||
void() hknight_char_a15=[ $char_a15, hknight_char_a16 ] {ai_charge(21);};
|
||||
void() hknight_char_a16=[ $char_a16, hknight_run1 ] {ai_charge(13);};
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void() hknight_char_b1 =[ $char_b1, hknight_char_b2 ]
|
||||
{CheckContinueCharge (); ai_charge(23); ai_melee();};
|
||||
void() hknight_char_b2 =[ $char_b2, hknight_char_b3 ] {ai_charge(17); ai_melee();};
|
||||
void() hknight_char_b3 =[ $char_b3, hknight_char_b4 ] {ai_charge(12); ai_melee();};
|
||||
void() hknight_char_b4 =[ $char_b4, hknight_char_b5 ] {ai_charge(22); ai_melee();};
|
||||
void() hknight_char_b5 =[ $char_b5, hknight_char_b6 ] {ai_charge(18); ai_melee();};
|
||||
void() hknight_char_b6 =[ $char_b6, hknight_char_b1 ] {ai_charge(8); ai_melee();};
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void() hknight_slice1 =[ $slice1, hknight_slice2 ] {ai_charge(9);};
|
||||
void() hknight_slice2 =[ $slice2, hknight_slice3 ] {ai_charge(6);};
|
||||
void() hknight_slice3 =[ $slice3, hknight_slice4 ] {ai_charge(13);};
|
||||
void() hknight_slice4 =[ $slice4, hknight_slice5 ] {ai_charge(4);};
|
||||
void() hknight_slice5 =[ $slice5, hknight_slice6 ] {ai_charge(7); ai_melee();};
|
||||
void() hknight_slice6 =[ $slice6, hknight_slice7 ] {ai_charge(15); ai_melee();};
|
||||
void() hknight_slice7 =[ $slice7, hknight_slice8 ] {ai_charge(8); ai_melee();};
|
||||
void() hknight_slice8 =[ $slice8, hknight_slice9 ] {ai_charge(2); ai_melee();};
|
||||
void() hknight_slice9 =[ $slice9, hknight_slice10 ] {ai_melee();};
|
||||
void() hknight_slice10 =[ $slice10, hknight_run1 ] {ai_charge(3);};
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void() hknight_smash1 =[ $smash1, hknight_smash2 ] {ai_charge(1);};
|
||||
void() hknight_smash2 =[ $smash2, hknight_smash3 ] {ai_charge(13);};
|
||||
void() hknight_smash3 =[ $smash3, hknight_smash4 ] {ai_charge(9);};
|
||||
void() hknight_smash4 =[ $smash4, hknight_smash5 ] {ai_charge(11);};
|
||||
void() hknight_smash5 =[ $smash5, hknight_smash6 ] {ai_charge(10); ai_melee();};
|
||||
void() hknight_smash6 =[ $smash6, hknight_smash7 ] {ai_charge(7); ai_melee();};
|
||||
void() hknight_smash7 =[ $smash7, hknight_smash8 ] {ai_charge(12); ai_melee();};
|
||||
void() hknight_smash8 =[ $smash8, hknight_smash9 ] {ai_charge(2); ai_melee();};
|
||||
void() hknight_smash9 =[ $smash9, hknight_smash10 ] {ai_charge(3); ai_melee();};
|
||||
void() hknight_smash10 =[ $smash10, hknight_smash11 ] {ai_charge(0);};
|
||||
void() hknight_smash11 =[ $smash11, hknight_run1 ] {ai_charge(0);};
|
||||
|
||||
//============================================================================
|
||||
|
||||
void() hknight_watk1 =[ $w_attack1, hknight_watk2 ] {ai_charge(2);};
|
||||
void() hknight_watk2 =[ $w_attack2, hknight_watk3 ] {ai_charge(0);};
|
||||
void() hknight_watk3 =[ $w_attack3, hknight_watk4 ] {ai_charge(0);};
|
||||
void() hknight_watk4 =[ $w_attack4, hknight_watk5 ] {ai_melee();};
|
||||
void() hknight_watk5 =[ $w_attack5, hknight_watk6 ] {ai_melee();};
|
||||
void() hknight_watk6 =[ $w_attack6, hknight_watk7 ] {ai_melee();};
|
||||
void() hknight_watk7 =[ $w_attack7, hknight_watk8 ] {ai_charge(1);};
|
||||
void() hknight_watk8 =[ $w_attack8, hknight_watk9 ] {ai_charge(4);};
|
||||
void() hknight_watk9 =[ $w_attack9, hknight_watk10 ] {ai_charge(5);};
|
||||
void() hknight_watk10 =[ $w_attack10, hknight_watk11 ] {ai_charge(3); ai_melee();};
|
||||
void() hknight_watk11 =[ $w_attack11, hknight_watk12 ] {ai_charge(2); ai_melee();};
|
||||
void() hknight_watk12 =[ $w_attack12, hknight_watk13 ] {ai_charge(2); ai_melee();};
|
||||
void() hknight_watk13 =[ $w_attack13, hknight_watk14 ] {ai_charge(0);};
|
||||
void() hknight_watk14 =[ $w_attack14, hknight_watk15 ] {ai_charge(0);};
|
||||
void() hknight_watk15 =[ $w_attack15, hknight_watk16 ] {ai_charge(0);};
|
||||
void() hknight_watk16 =[ $w_attack16, hknight_watk17 ] {ai_charge(1);};
|
||||
void() hknight_watk17 =[ $w_attack17, hknight_watk18 ] {ai_charge(1); ai_melee();};
|
||||
void() hknight_watk18 =[ $w_attack18, hknight_watk19 ] {ai_charge(3); ai_melee();};
|
||||
void() hknight_watk19 =[ $w_attack19, hknight_watk20 ] {ai_charge(4); ai_melee();};
|
||||
void() hknight_watk20 =[ $w_attack20, hknight_watk21 ] {ai_charge(6);};
|
||||
void() hknight_watk21 =[ $w_attack21, hknight_watk22 ] {ai_charge(7);};
|
||||
void() hknight_watk22 =[ $w_attack22, hknight_run1 ] {ai_charge(3);};
|
||||
|
||||
//============================================================================
|
||||
|
||||
void() hk_idle_sound =
|
||||
{
|
||||
if (random() < 0.2)
|
||||
sound (self, CHAN_VOICE, "hknight/idle.wav", 1, ATTN_NORM);
|
||||
};
|
||||
|
||||
void(entity attacker, float damage) hknight_pain =
|
||||
{
|
||||
if (self.pain_finished > time)
|
||||
return;
|
||||
|
||||
if (random() < 0.6)
|
||||
sound (self, CHAN_VOICE, "hknight/pain1.wav", 1, ATTN_NORM);
|
||||
else
|
||||
sound (self, CHAN_VOICE, "hknight/grunt.wav", 1, ATTN_NORM);
|
||||
|
||||
if (time - self.pain_finished > 5)
|
||||
{ // allways go into pain frame if it has been a while
|
||||
hknight_pain1 ();
|
||||
self.pain_finished = time + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((random()*30 > damage) )
|
||||
return; // didn't flinch
|
||||
|
||||
self.pain_finished = time + 1;
|
||||
hknight_pain1 ();
|
||||
};
|
||||
|
||||
float hknight_type;
|
||||
|
||||
void() hknight_melee =
|
||||
{
|
||||
hknight_type = hknight_type + 1;
|
||||
|
||||
sound (self, CHAN_WEAPON, "hknight/slash1.wav", 1, ATTN_NORM);
|
||||
if (hknight_type == 1)
|
||||
hknight_slice1 ();
|
||||
else if (hknight_type == 2)
|
||||
hknight_smash1 ();
|
||||
else if (hknight_type == 3)
|
||||
{
|
||||
hknight_watk1 ();
|
||||
hknight_type = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/*QUAKED monster_hell_knight (1 0 0) (-16 -16 -24) (16 16 40) Ambush
|
||||
{
|
||||
model ("progs/hknight.mdl");
|
||||
}
|
||||
Death knight.
|
||||
*/
|
||||
void() monster_hell_knight =
|
||||
{
|
||||
if (deathmatch)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
precache_model2 ("progs/hknight.mdl");
|
||||
precache_model2 ("progs/h_hellkn.mdl");
|
||||
precache_model2 ("progs/k_spike.mdl");
|
||||
|
||||
precache_sound2 ("hknight/attack1.wav");
|
||||
precache_sound2 ("hknight/death1.wav");
|
||||
precache_sound2 ("hknight/pain1.wav");
|
||||
precache_sound2 ("hknight/sight1.wav");
|
||||
precache_sound2 ("hknight/slash1.wav");
|
||||
precache_sound2 ("hknight/idle.wav");
|
||||
precache_sound2 ("hknight/grunt.wav");
|
||||
precache_sound ("hknight/hit.wav");
|
||||
precache_sound ("knight/sword1.wav");
|
||||
precache_sound ("knight/sword2.wav");
|
||||
|
||||
self.th_stand = hknight_stand1;
|
||||
self.th_walk = hknight_walk1;
|
||||
self.th_run = hknight_run1;
|
||||
self.th_melee = hknight_melee;
|
||||
self.th_missile = hknight_magicc1;
|
||||
self.th_pain = hknight_pain;
|
||||
self.th_die = hknight_die;
|
||||
|
||||
monster_start("progs/hknight.mdl", "progs/h_hellkn.mdl", 250, 0, '-16 -16 -24', '16 16 40');
|
||||
};
|
||||
241
mod_slipgate/source/server/monsters/knight.qc
Normal file
241
mod_slipgate/source/server/monsters/knight.qc
Normal file
@@ -0,0 +1,241 @@
|
||||
$frame stand1 stand2 stand3 stand4 stand5 stand6 stand7 stand8 stand9
|
||||
|
||||
$frame runb1 runb2 runb3 runb4 runb5 runb6 runb7 runb8
|
||||
|
||||
$frame runattack1 runattack2 runattack3 runattack4 runattack5
|
||||
$frame runattack6 runattack7 runattack8 runattack9 runattack10
|
||||
$frame runattack11
|
||||
|
||||
$frame pain1 pain2 pain3
|
||||
|
||||
$frame painb1 painb2 painb3 painb4 painb5 painb6 painb7 painb8 painb9
|
||||
$frame painb10 painb11
|
||||
|
||||
$frame attackx1
|
||||
$frame attackb1 attackb2 attackb3 attackb4 attackb5
|
||||
$frame attackb6 attackb7 attackb8 attackb9 attackb10
|
||||
|
||||
$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8 walk9
|
||||
$frame walk10 walk11 walk12 walk13 walk14
|
||||
|
||||
$frame kneel1 kneel2 kneel3 kneel4 kneel5
|
||||
|
||||
$frame standing1 standing2 standing3 standing4
|
||||
|
||||
$frame death1 death2 death3 death4 death5 death6 death7 death8
|
||||
$frame death9 death10 death11
|
||||
|
||||
$frame deathb1 deathb2 deathb3 deathb4 deathb5 deathb6 deathb7 deathb8
|
||||
$frame deathb9 deathb10
|
||||
|
||||
void() knight_stand1 =[ $stand1, knight_stand2 ] {ai_stand();};
|
||||
void() knight_stand2 =[ $stand2, knight_stand3 ] {ai_stand();};
|
||||
void() knight_stand3 =[ $stand3, knight_stand4 ] {ai_stand();};
|
||||
void() knight_stand4 =[ $stand4, knight_stand5 ] {ai_stand();};
|
||||
void() knight_stand5 =[ $stand5, knight_stand6 ] {ai_stand();};
|
||||
void() knight_stand6 =[ $stand6, knight_stand7 ] {ai_stand();};
|
||||
void() knight_stand7 =[ $stand7, knight_stand8 ] {ai_stand();};
|
||||
void() knight_stand8 =[ $stand8, knight_stand9 ] {ai_stand();};
|
||||
void() knight_stand9 =[ $stand9, knight_stand1 ] {ai_stand();};
|
||||
|
||||
void() knight_walk1 =[ $walk1, knight_walk2 ] {
|
||||
if (random() < 0.2)
|
||||
sound (self, CHAN_VOICE, "knight/idle.wav", 1, ATTN_IDLE);
|
||||
ai_walk(3);};
|
||||
void() knight_walk2 =[ $walk2, knight_walk3 ] {ai_walk(2);};
|
||||
void() knight_walk3 =[ $walk3, knight_walk4 ] {ai_walk(3);};
|
||||
void() knight_walk4 =[ $walk4, knight_walk5 ] {ai_walk(4);};
|
||||
void() knight_walk5 =[ $walk5, knight_walk6 ] {ai_walk(3);};
|
||||
void() knight_walk6 =[ $walk6, knight_walk7 ] {ai_walk(3);};
|
||||
void() knight_walk7 =[ $walk7, knight_walk8 ] {ai_walk(3);};
|
||||
void() knight_walk8 =[ $walk8, knight_walk9 ] {ai_walk(4);};
|
||||
void() knight_walk9 =[ $walk9, knight_walk10 ] {ai_walk(3);};
|
||||
void() knight_walk10 =[ $walk10, knight_walk11 ] {ai_walk(3);};
|
||||
void() knight_walk11 =[ $walk11, knight_walk12 ] {ai_walk(2);};
|
||||
void() knight_walk12 =[ $walk12, knight_walk13 ] {ai_walk(3);};
|
||||
void() knight_walk13 =[ $walk13, knight_walk14 ] {ai_walk(4);};
|
||||
void() knight_walk14 =[ $walk14, knight_walk1 ] {ai_walk(3);};
|
||||
|
||||
|
||||
void() knight_run1 =[ $runb1, knight_run2 ] {
|
||||
if (random() < 0.2)
|
||||
sound (self, CHAN_VOICE, "knight/idle.wav", 1, ATTN_IDLE);
|
||||
ai_run(16);};
|
||||
void() knight_run2 =[ $runb2, knight_run3 ] {ai_run(20);};
|
||||
void() knight_run3 =[ $runb3, knight_run4 ] {ai_run(13);};
|
||||
void() knight_run4 =[ $runb4, knight_run5 ] {ai_run(7);};
|
||||
void() knight_run5 =[ $runb5, knight_run6 ] {ai_run(16);};
|
||||
void() knight_run6 =[ $runb6, knight_run7 ] {ai_run(20);};
|
||||
void() knight_run7 =[ $runb7, knight_run8 ] {ai_run(14);};
|
||||
void() knight_run8 =[ $runb8, knight_run1 ] {ai_run(6);};
|
||||
|
||||
|
||||
void() knight_runatk1 =[ $runattack1, knight_runatk2 ]
|
||||
{
|
||||
if (random() > 0.5)
|
||||
sound (self, CHAN_WEAPON, "knight/sword2.wav", 1, ATTN_NORM);
|
||||
else
|
||||
sound (self, CHAN_WEAPON, "knight/sword1.wav", 1, ATTN_NORM);
|
||||
ai_charge(20);
|
||||
};
|
||||
void() knight_runatk2 =[ $runattack2, knight_runatk3 ] {ai_charge_side();};
|
||||
void() knight_runatk3 =[ $runattack3, knight_runatk4 ] {ai_charge_side();};
|
||||
void() knight_runatk4 =[ $runattack4, knight_runatk5 ] {ai_charge_side();};
|
||||
void() knight_runatk5 =[ $runattack5, knight_runatk6 ] {ai_melee_side();};
|
||||
void() knight_runatk6 =[ $runattack6, knight_runatk7 ] {ai_melee_side();};
|
||||
void() knight_runatk7 =[ $runattack7, knight_runatk8 ] {ai_melee_side();};
|
||||
void() knight_runatk8 =[ $runattack8, knight_runatk9 ] {ai_melee_side();};
|
||||
void() knight_runatk9 =[ $runattack9, knight_runatk10 ] {ai_melee_side();};
|
||||
void() knight_runatk10 =[ $runattack10, knight_runatk11 ] {ai_charge_side();};
|
||||
void() knight_runatk11 =[ $runattack11, knight_run1 ] {ai_charge(10);};
|
||||
|
||||
void() knight_atk1 =[ $attackb1, knight_atk2 ]
|
||||
{
|
||||
sound (self, CHAN_WEAPON, "knight/sword1.wav", 1, ATTN_NORM);
|
||||
ai_charge(0);};
|
||||
void() knight_atk2 =[ $attackb2, knight_atk3 ] {ai_charge(7);};
|
||||
void() knight_atk3 =[ $attackb3, knight_atk4 ] {ai_charge(4);};
|
||||
void() knight_atk4 =[ $attackb4, knight_atk5 ] {ai_charge(0);};
|
||||
void() knight_atk5 =[ $attackb5, knight_atk6 ] {ai_charge(3);};
|
||||
void() knight_atk6 =[ $attackb6, knight_atk7 ] {ai_charge(4); ai_melee();};
|
||||
void() knight_atk7 =[ $attackb7, knight_atk8 ] {ai_charge(1); ai_melee();};
|
||||
void() knight_atk8 =[ $attackb8, knight_atk9 ] {ai_charge(3); ai_melee();};
|
||||
void() knight_atk9 =[ $attackb9, knight_atk10] {ai_charge(1);};
|
||||
void() knight_atk10=[ $attackb10, knight_run1 ] {ai_charge(5);};
|
||||
|
||||
void() knight_attack =
|
||||
{
|
||||
local float len;
|
||||
|
||||
// decide if now is a good swing time
|
||||
len = vlen(self.enemy.origin+self.enemy.view_ofs - (self.origin+self.view_ofs));
|
||||
|
||||
if (len<80)
|
||||
knight_atk1 ();
|
||||
else
|
||||
knight_runatk1 ();
|
||||
};
|
||||
|
||||
void() knight_pain1 =[ $pain1, knight_pain2 ] {};
|
||||
void() knight_pain2 =[ $pain2, knight_pain3 ] {};
|
||||
void() knight_pain3 =[ $pain3, knight_run1 ] {};
|
||||
|
||||
void() knight_painb1 =[ $painb1, knight_painb2 ] {ai_painforward(0);};
|
||||
void() knight_painb2 =[ $painb2, knight_painb3 ] {ai_painforward(3);};
|
||||
void() knight_painb3 =[ $painb3, knight_painb4 ] {};
|
||||
void() knight_painb4 =[ $painb4, knight_painb5 ] {};
|
||||
void() knight_painb5 =[ $painb5, knight_painb6 ] {ai_painforward(2);};
|
||||
void() knight_painb6 =[ $painb6, knight_painb7 ] {ai_painforward(4);};
|
||||
void() knight_painb7 =[ $painb7, knight_painb8 ] {ai_painforward(2);};
|
||||
void() knight_painb8 =[ $painb8, knight_painb9 ] {ai_painforward(5);};
|
||||
void() knight_painb9 =[ $painb9, knight_painb10 ] {ai_painforward(5);};
|
||||
void() knight_painb10 =[ $painb10, knight_painb11 ] {ai_painforward(0);};
|
||||
void() knight_painb11 =[ $painb11, knight_run1 ] {};
|
||||
|
||||
void(entity attacker, float damage) knight_pain =
|
||||
{
|
||||
if (self.pain_finished > time)
|
||||
return;
|
||||
|
||||
if (random() < 0.8)
|
||||
sound (self, CHAN_VOICE, "knight/khurt.wav", 1, ATTN_NORM);
|
||||
else
|
||||
sound (self, CHAN_VOICE, "hknight/grunt.wav", 1, ATTN_NORM);
|
||||
|
||||
float r = random();
|
||||
if (r < 0.85)
|
||||
{
|
||||
knight_pain1 ();
|
||||
self.pain_finished = time + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
knight_painb1 ();
|
||||
self.pain_finished = time + 1;
|
||||
}
|
||||
};
|
||||
|
||||
void() knight_die1 =[ $death1, knight_die2 ] {};
|
||||
void() knight_die2 =[ $death2, knight_die3 ] {};
|
||||
void() knight_die3 =[ $death3, knight_die4 ] {};
|
||||
void() knight_die4 =[ $death4, knight_die5 ] {};
|
||||
void() knight_die5 =[ $death5, knight_die6 ] {};
|
||||
void() knight_die6 =[ $death6, knight_die7 ] {};
|
||||
void() knight_die7 =[ $death7, knight_die8 ] {};
|
||||
void() knight_die8 =[ $death8, knight_die9 ] {};
|
||||
void() knight_die9 =[ $death9, knight_die10] {};
|
||||
void() knight_die10=[ $death10, knight_die10] {};
|
||||
void() knight_die11=[ $death11, knight_die11] {};
|
||||
|
||||
void() knight_dieb1 =[ $deathb1, knight_dieb2 ] {};
|
||||
void() knight_dieb2 =[ $deathb2, knight_dieb3 ] {};
|
||||
void() knight_dieb3 =[ $deathb3, knight_dieb4 ] {};
|
||||
void() knight_dieb4 =[ $deathb4, knight_dieb5 ] {};
|
||||
void() knight_dieb5 =[ $deathb5, knight_dieb6 ] {};
|
||||
void() knight_dieb6 =[ $deathb6, knight_dieb7 ] {};
|
||||
void() knight_dieb7 =[ $deathb7, knight_dieb8 ] {};
|
||||
void() knight_dieb8 =[ $deathb8, knight_dieb9 ] {};
|
||||
void() knight_dieb9 =[ $deathb9, knight_dieb10] {};
|
||||
void() knight_dieb10 = [ $deathb10, knight_dieb10] {};
|
||||
|
||||
void(entity inflictor, entity attacker) knight_die =
|
||||
{
|
||||
// check for gib
|
||||
if (self.health < -40)
|
||||
{
|
||||
SpawnGib ("progs/gib1.mdl");
|
||||
SpawnGib ("progs/gib2.mdl");
|
||||
SpawnGib ("progs/gib3.mdl");
|
||||
SpawnGib ("progs/gib4.mdl");
|
||||
SpawnGib ("progs/gib5.mdl");
|
||||
SpawnGib ("progs/blood.mdl");
|
||||
SpawnGib ("progs/blood.mdl");
|
||||
BecomeGibs ();
|
||||
return;
|
||||
}
|
||||
|
||||
// regular death
|
||||
self.solid = SOLID_NOT;
|
||||
sound (self, CHAN_VOICE, "knight/kdeath.wav", 1, ATTN_NORM);
|
||||
if (random() < 0.5)
|
||||
knight_die1();
|
||||
else
|
||||
knight_dieb1();
|
||||
};
|
||||
|
||||
/*QUAKED monster_knight (1 0 0) (-16 -16 -24) (16 16 40) Ambush
|
||||
{
|
||||
model ("progs/knight.mdl");
|
||||
}
|
||||
Knight.
|
||||
*/
|
||||
void() monster_knight =
|
||||
{
|
||||
if (deathmatch)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
precache_model ("progs/knight.mdl");
|
||||
precache_model ("progs/h_knight.mdl");
|
||||
|
||||
precache_sound ("knight/kdeath.wav");
|
||||
precache_sound ("knight/khurt.wav");
|
||||
precache_sound ("knight/ksight.wav");
|
||||
precache_sound ("knight/sword1.wav");
|
||||
precache_sound ("knight/sword2.wav");
|
||||
precache_sound ("knight/idle.wav");
|
||||
precache_sound ("hknight/grunt.wav");
|
||||
|
||||
self.th_stand = knight_stand1;
|
||||
self.th_walk = knight_walk1;
|
||||
self.th_run = knight_run1;
|
||||
self.th_melee = knight_attack;
|
||||
self.th_pain = knight_pain;
|
||||
self.th_die = knight_die;
|
||||
|
||||
self.skin = randomrange(4);
|
||||
|
||||
monster_start("progs/knight.mdl", "progs/h_knight.mdl", 75, 0, '-16 -16 -24', '16 16 40');
|
||||
};
|
||||
|
||||
485
mod_slipgate/source/server/monsters/ogre.qc
Normal file
485
mod_slipgate/source/server/monsters/ogre.qc
Normal file
@@ -0,0 +1,485 @@
|
||||
$frame stand1 stand2 stand3 stand4 stand5 stand6 stand7 stand8 stand9
|
||||
|
||||
$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7
|
||||
$frame walk8 walk9 walk10 walk11 walk12 walk13 walk14 walk15 walk16
|
||||
|
||||
$frame run1 run2 run3 run4 run5 run6 run7 run8
|
||||
|
||||
$frame swing1 swing2 swing3 swing4 swing5 swing6 swing7
|
||||
$frame swing8 swing9 swing10 swing11 swing12 swing13 swing14
|
||||
|
||||
$frame smash1 smash2 smash3 smash4 smash5 smash6 smash7
|
||||
$frame smash8 smash9 smash10 smash11 smash12 smash13 smash14
|
||||
|
||||
$frame shoot1 shoot2 shoot3 shoot4 shoot5 shoot6
|
||||
|
||||
$frame pain1 pain2 pain3 pain4 pain5
|
||||
|
||||
$frame painb1 painb2 painb3
|
||||
|
||||
$frame painc1 painc2 painc3 painc4 painc5 painc6
|
||||
|
||||
$frame paind1 paind2 paind3 paind4 paind5 paind6 paind7 paind8 paind9 paind10
|
||||
$frame paind11 paind12 paind13 paind14 paind15 paind16
|
||||
|
||||
$frame paine1 paine2 paine3 paine4 paine5 paine6 paine7 paine8 paine9 paine10
|
||||
$frame paine11 paine12 paine13 paine14 paine15
|
||||
|
||||
$frame death1 death2 death3 death4 death5 death6
|
||||
$frame death7 death8 death9 death10 death11 death12
|
||||
$frame death13 death14
|
||||
|
||||
$frame bdeath1 bdeath2 bdeath3 bdeath4 bdeath5 bdeath6
|
||||
$frame bdeath7 bdeath8 bdeath9 bdeath10
|
||||
|
||||
$frame pull1 pull2 pull3 pull4 pull5 pull6 pull7 pull8 pull9 pull10 pull11
|
||||
|
||||
#define OGRE_G_VEL 600
|
||||
#define OGRE_DEFAULT_ELEVATION 45
|
||||
|
||||
/*==========
|
||||
OgreGrenadeExplode
|
||||
==========*/
|
||||
void() OgreGrenadeExplode =
|
||||
{
|
||||
RadiusDamage(self, self.owner, 40, world);
|
||||
te_explosion(self.origin);
|
||||
BecomeExplosion();
|
||||
};
|
||||
|
||||
/*==========
|
||||
OgreGrenadeTouch
|
||||
==========*/
|
||||
void() OgreGrenadeTouch =
|
||||
{
|
||||
if (other.takedamage == DAMAGE_AIM)
|
||||
{
|
||||
OgreGrenadeExplode();
|
||||
return;
|
||||
}
|
||||
sound(self, CHAN_VOICE, "weapons/bounce.wav", 1, ATTN_NORM);
|
||||
};
|
||||
|
||||
/*==========
|
||||
OgreIterateElevation
|
||||
==========*/
|
||||
float(float theta, vector dest, vector org) OgreIterateElevation =
|
||||
{
|
||||
vector ofs = dest - org;
|
||||
float z = ofs_z;
|
||||
ofs_z = 0;
|
||||
float y = vlen(ofs);
|
||||
|
||||
float a = 0.5 * sv_gravity * y * y / (OGRE_G_VEL * OGRE_G_VEL);
|
||||
float b = -y;
|
||||
float c = a + z;
|
||||
|
||||
// can't reach target
|
||||
if (b * b < 4 * a * c)
|
||||
{
|
||||
dprint("OGRE_DEFAULT_ELEVATION\n");
|
||||
return OGRE_DEFAULT_ELEVATION;
|
||||
}
|
||||
|
||||
float tan_theta = tan(theta);
|
||||
theta = atan2(a * tan_theta * tan_theta - c, 2 * a * tan_theta + b);
|
||||
|
||||
while (theta > 90)
|
||||
theta = theta - 180;
|
||||
return theta;
|
||||
};
|
||||
|
||||
/*==========
|
||||
OgreFireGrenade
|
||||
==========*/
|
||||
void(float spam) OgreFireGrenade =
|
||||
{
|
||||
self.effects = self.effects | EF_MUZZLEFLASH;
|
||||
|
||||
sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
|
||||
|
||||
vector org = self.origin;
|
||||
|
||||
entity missile = spawn ();
|
||||
missile.owner = self;
|
||||
missile.movetype = MOVETYPE_BOUNCE;
|
||||
missile.solid = SOLID_BBOX;
|
||||
|
||||
setmodel (missile, "progs/grenade.mdl");
|
||||
setsize (missile, '0 0 0', '0 0 0');
|
||||
setorigin (missile, org);
|
||||
|
||||
// chose where to aim
|
||||
vector dest;
|
||||
// aim at last known enemy location
|
||||
if (spam)
|
||||
{
|
||||
dest = self.enemy_last;
|
||||
spawn_debug_marker(dest);
|
||||
}
|
||||
// aim at enemy
|
||||
else
|
||||
{
|
||||
// lead player on hard
|
||||
/*if (skill > 1)
|
||||
{
|
||||
vector ofs = self.enemy.origin + self.enemy.view_ofs - org;
|
||||
float t = vlen(ofs) / OGRE_G_VEL;
|
||||
vector vel = self.enemy.velocity;
|
||||
vel_z = 0;
|
||||
dest = self.enemy.origin + self.enemy.view_ofs + (t * vel);
|
||||
}
|
||||
// aim at enemy position
|
||||
else
|
||||
*/
|
||||
dest = self.enemy.origin + self.enemy.view_ofs;
|
||||
}
|
||||
float elevation = OgreIterateElevation(OGRE_DEFAULT_ELEVATION, dest, org);
|
||||
elevation = OgreIterateElevation(elevation, dest, org);
|
||||
elevation = OgreIterateElevation(elevation, dest, org);
|
||||
elevation = OgreIterateElevation(elevation, dest, org);
|
||||
|
||||
vector ang = normalize(dest - org);
|
||||
ang = vectoangles(ang);
|
||||
ang_x = -elevation;
|
||||
makevectors(ang);
|
||||
|
||||
missile.velocity = v_forward * OGRE_G_VEL;
|
||||
missile.avelocity = '300 300 300';
|
||||
missile.angles = vectoangles(missile.velocity);
|
||||
missile.touch = OgreGrenadeTouch;
|
||||
|
||||
missile.nextthink = time + 2.5;
|
||||
missile.think = OgreGrenadeExplode;
|
||||
};
|
||||
|
||||
void() ogre_grenade1 =[ $shoot1, ogre_grenade2 ] {ai_face();};
|
||||
void() ogre_grenade2 =[ $shoot2, ogre_grenade3 ] {ai_face();};
|
||||
void() ogre_grenade3 =[ $shoot2, ogre_grenade4 ] {ai_face();};
|
||||
void() ogre_grenade4 =[ $shoot3, ogre_grenade5 ] {ai_face();OgreFireGrenade(FALSE);};
|
||||
void() ogre_grenade5 =[ $shoot4, ogre_grenade6 ] {ai_face();};
|
||||
void() ogre_grenade6 =[ $shoot5, ogre_grenade7 ] {ai_face();};
|
||||
void() ogre_grenade7 =[ $shoot6, ogre_run1 ] {ai_face();};
|
||||
|
||||
void() ogre_spam1 =[ $shoot1, ogre_spam2 ] {ai_face_last();};
|
||||
void() ogre_spam2 =[ $shoot2, ogre_spam3 ] {ai_face_last();};
|
||||
void() ogre_spam3 =[ $shoot2, ogre_spam4 ] {ai_face_last();};
|
||||
void() ogre_spam4 =[ $shoot3, ogre_spam5 ] {ai_face_last();OgreFireGrenade(TRUE);};
|
||||
void() ogre_spam5 =[ $shoot4, ogre_spam6 ] {ai_face_last();};
|
||||
void() ogre_spam6 =[ $shoot5, ogre_spam7 ] {ai_face_last();};
|
||||
void() ogre_spam7 =[ $shoot6, ogre_run1 ] {ai_face_last();};
|
||||
|
||||
/*==========
|
||||
OgreChainsaw
|
||||
==========*/
|
||||
void() OgreChainsaw =
|
||||
{
|
||||
float delta = vlen(self.enemy.origin - self.origin);
|
||||
if (delta > 100)
|
||||
return;
|
||||
if (!CanDamage(self.enemy, self))
|
||||
return;
|
||||
|
||||
float ldmg = (random() + random() + random()) * 4;
|
||||
Damage (self.enemy, self, self, ldmg);
|
||||
|
||||
SpawnBlood(trace_endpos, randomvec() * 8, 12);
|
||||
if (random() < 0.1)
|
||||
{
|
||||
makevectors (self.angles);
|
||||
if (random() < 0.5)
|
||||
SpawnMeatSpray (self.origin + v_forward*16, v_right * 200 + v_up * 50);
|
||||
else
|
||||
SpawnMeatSpray (self.origin + v_forward*16, v_up * 50 - v_right * 200);
|
||||
}
|
||||
};
|
||||
|
||||
void() ogre_swing1 =[ $swing1, ogre_swing2 ] {ai_charge(11);};
|
||||
void() ogre_swing2 =[ $swing2, ogre_swing3 ] {ai_charge(1);};
|
||||
void() ogre_swing3 =[ $swing3, ogre_swing4 ] {ai_charge(4);};
|
||||
void() ogre_swing4 =[ $swing4, ogre_swing5 ] {ai_charge(13);};
|
||||
void() ogre_swing5 =[ $swing5, ogre_swing6 ] {ai_charge(19);OgreChainsaw();};
|
||||
void() ogre_swing6 =[ $swing6, ogre_swing7 ] {ai_charge(10);OgreChainsaw();};
|
||||
void() ogre_swing7 =[ $swing7, ogre_swing8 ] {ai_charge(10);OgreChainsaw();};
|
||||
void() ogre_swing8 =[ $swing8, ogre_swing9 ] {ai_charge(10);OgreChainsaw();};
|
||||
void() ogre_swing9 =[ $swing9, ogre_swing10] {ai_charge(10);OgreChainsaw();};
|
||||
void() ogre_swing10 =[ $swing10, ogre_swing11] {ai_charge(10);OgreChainsaw();};
|
||||
void() ogre_swing11 =[ $swing11, ogre_swing12] {ai_charge(10);OgreChainsaw();};
|
||||
void() ogre_swing12 =[ $swing12, ogre_swing13] {ai_charge(3);};
|
||||
void() ogre_swing13 =[ $swing13, ogre_swing14] {ai_charge(8);};
|
||||
void() ogre_swing14 =[ $swing14, ogre_run1 ] {ai_charge(9);};
|
||||
|
||||
void() ogre_smash1 =[ $smash1, ogre_smash2 ] {ai_charge(6);};
|
||||
void() ogre_smash2 =[ $smash2, ogre_smash3 ] {ai_charge(0);};
|
||||
void() ogre_smash3 =[ $smash3, ogre_smash4 ] {ai_charge(0);};
|
||||
void() ogre_smash4 =[ $smash4, ogre_smash5 ] {ai_charge(1);};
|
||||
void() ogre_smash5 =[ $smash5, ogre_smash6 ] {ai_charge(4);};
|
||||
void() ogre_smash6 =[ $smash6, ogre_smash7 ] {ai_charge(14);OgreChainsaw();};
|
||||
void() ogre_smash7 =[ $smash7, ogre_smash8 ] {ai_charge(14);OgreChainsaw();};
|
||||
void() ogre_smash8 =[ $smash8, ogre_smash9 ] {ai_charge(20);OgreChainsaw();};
|
||||
void() ogre_smash9 =[ $smash9, ogre_smash10] {ai_charge(23);OgreChainsaw();};
|
||||
void() ogre_smash10 =[ $smash10, ogre_smash11] {ai_charge(10);OgreChainsaw();};
|
||||
void() ogre_smash11 =[ $smash11, ogre_smash12]
|
||||
{
|
||||
ai_charge(12);
|
||||
OgreChainsaw();
|
||||
self.nextthink = self.nextthink + random()*0.2;
|
||||
};
|
||||
void() ogre_smash12 =[ $smash12, ogre_smash13 ] {ai_charge(0);};
|
||||
void() ogre_smash13 =[ $smash13, ogre_smash14 ] {ai_charge(4);};
|
||||
void() ogre_smash14 =[ $smash14, ogre_run1 ] {ai_charge(12);};
|
||||
|
||||
/*==========
|
||||
ogre_melee
|
||||
==========*/
|
||||
void() ogre_melee =
|
||||
{
|
||||
sound (self, CHAN_WEAPON, "ogre/ogsawatk.wav", 1, ATTN_NORM);
|
||||
if (random() < 0.5)
|
||||
ogre_smash1();
|
||||
else
|
||||
ogre_swing1();
|
||||
};
|
||||
|
||||
void() ogre_stand1 =[ $stand1, ogre_stand2 ] {ai_stand();};
|
||||
void() ogre_stand2 =[ $stand2, ogre_stand3 ] {ai_stand();};
|
||||
void() ogre_stand3 =[ $stand3, ogre_stand4 ] {ai_stand();};
|
||||
void() ogre_stand4 =[ $stand4, ogre_stand5 ] {ai_stand();};
|
||||
void() ogre_stand5 =[ $stand5, ogre_stand6 ] {
|
||||
if (random() < 0.2)
|
||||
sound (self, CHAN_VOICE, "ogre/ogidle.wav", 1, ATTN_IDLE);
|
||||
ai_stand();
|
||||
};
|
||||
void() ogre_stand6 =[ $stand6, ogre_stand7 ] {ai_stand();};
|
||||
void() ogre_stand7 =[ $stand7, ogre_stand8 ] {ai_stand();};
|
||||
void() ogre_stand8 =[ $stand8, ogre_stand9 ] {ai_stand();};
|
||||
void() ogre_stand9 =[ $stand9, ogre_stand1 ] {ai_stand();};
|
||||
|
||||
void() ogre_walk1 =[ $walk1, ogre_walk2 ] {ai_walk(3);};
|
||||
void() ogre_walk2 =[ $walk2, ogre_walk3 ] {ai_walk(2);};
|
||||
void() ogre_walk3 =[ $walk3, ogre_walk4 ] {ai_walk(2);
|
||||
if (random() < 0.2)
|
||||
sound (self, CHAN_VOICE, "ogre/ogidle.wav", 1, ATTN_IDLE);
|
||||
};
|
||||
void() ogre_walk4 =[ $walk4, ogre_walk5 ] {ai_walk(2);};
|
||||
void() ogre_walk5 =[ $walk5, ogre_walk6 ] {ai_walk(2);};
|
||||
void() ogre_walk6 =[ $walk6, ogre_walk7 ] {ai_walk(5);
|
||||
if (random() < 0.1)
|
||||
sound (self, CHAN_VOICE, "ogre/ogdrag.wav", 1, ATTN_IDLE);
|
||||
};
|
||||
void() ogre_walk7 =[ $walk7, ogre_walk8 ] {ai_walk(3);};
|
||||
void() ogre_walk8 =[ $walk8, ogre_walk9 ] {ai_walk(2);};
|
||||
void() ogre_walk9 =[ $walk9, ogre_walk10 ] {ai_walk(3);};
|
||||
void() ogre_walk10 =[ $walk10, ogre_walk11 ] {ai_walk(1);};
|
||||
void() ogre_walk11 =[ $walk11, ogre_walk12 ] {ai_walk(2);};
|
||||
void() ogre_walk12 =[ $walk12, ogre_walk13 ] {ai_walk(3);};
|
||||
void() ogre_walk13 =[ $walk13, ogre_walk14 ] {ai_walk(3);};
|
||||
void() ogre_walk14 =[ $walk14, ogre_walk15 ] {ai_walk(3);};
|
||||
void() ogre_walk15 =[ $walk15, ogre_walk16 ] {ai_walk(3);};
|
||||
void() ogre_walk16 =[ $walk16, ogre_walk1 ] {ai_walk(4);};
|
||||
|
||||
void() ogre_run1 =[ $run1, ogre_run2 ] {ai_run(9);
|
||||
if (random() < 0.2)
|
||||
sound (self, CHAN_VOICE, "ogre/ogidle2.wav", 1, ATTN_IDLE);
|
||||
};
|
||||
void() ogre_run2 =[ $run2, ogre_run3 ] {ai_run(12);};
|
||||
void() ogre_run3 =[ $run3, ogre_run4 ] {ai_run(8);};
|
||||
void() ogre_run4 =[ $run4, ogre_run5 ] {ai_run(22);};
|
||||
void() ogre_run5 =[ $run5, ogre_run6 ] {ai_run(16);};
|
||||
void() ogre_run6 =[ $run6, ogre_run7 ] {ai_run(4);};
|
||||
void() ogre_run7 =[ $run7, ogre_run8 ] {ai_run(13);};
|
||||
void() ogre_run8 =[ $run8, ogre_run1 ] {ai_run(24);};
|
||||
|
||||
void() ogre_pain1 =[ $pain1, ogre_pain2 ] {};
|
||||
void() ogre_pain2 =[ $pain2, ogre_pain3 ] {};
|
||||
void() ogre_pain3 =[ $pain3, ogre_pain4 ] {};
|
||||
void() ogre_pain4 =[ $pain4, ogre_pain5 ] {};
|
||||
void() ogre_pain5 =[ $pain5, ogre_run1 ] {};
|
||||
|
||||
void() ogre_painb1 =[ $painb1, ogre_painb2 ] {};
|
||||
void() ogre_painb2 =[ $painb2, ogre_painb3 ] {};
|
||||
void() ogre_painb3 =[ $painb3, ogre_run1 ] {};
|
||||
|
||||
void() ogre_painc1 =[ $painc1, ogre_painc2 ] {};
|
||||
void() ogre_painc2 =[ $painc2, ogre_painc3 ] {};
|
||||
void() ogre_painc3 =[ $painc3, ogre_painc4 ] {};
|
||||
void() ogre_painc4 =[ $painc4, ogre_painc5 ] {};
|
||||
void() ogre_painc5 =[ $painc5, ogre_painc6 ] {};
|
||||
void() ogre_painc6 =[ $painc6, ogre_run1 ] {};
|
||||
|
||||
void() ogre_paind1 =[ $paind1, ogre_paind2 ] {};
|
||||
void() ogre_paind2 =[ $paind2, ogre_paind3 ] {ai_pain(10);};
|
||||
void() ogre_paind3 =[ $paind3, ogre_paind4 ] {ai_pain(9);};
|
||||
void() ogre_paind4 =[ $paind4, ogre_paind5 ] {ai_pain(4);};
|
||||
void() ogre_paind5 =[ $paind5, ogre_paind6 ] {};
|
||||
void() ogre_paind6 =[ $paind6, ogre_paind7 ] {};
|
||||
void() ogre_paind7 =[ $paind7, ogre_paind8 ] {};
|
||||
void() ogre_paind8 =[ $paind8, ogre_paind9 ] {};
|
||||
void() ogre_paind9 =[ $paind9, ogre_paind10] {};
|
||||
void() ogre_paind10=[ $paind10, ogre_paind11] {};
|
||||
void() ogre_paind11=[ $paind11, ogre_paind12] {};
|
||||
void() ogre_paind12=[ $paind12, ogre_paind13] {};
|
||||
void() ogre_paind13=[ $paind13, ogre_paind14] {};
|
||||
void() ogre_paind14=[ $paind14, ogre_paind15] {};
|
||||
void() ogre_paind15=[ $paind15, ogre_paind16] {};
|
||||
void() ogre_paind16=[ $paind16, ogre_run1 ] {};
|
||||
|
||||
void() ogre_paine1 =[ $paine1, ogre_paine2 ] {};
|
||||
void() ogre_paine2 =[ $paine2, ogre_paine3 ] {ai_pain(10);};
|
||||
void() ogre_paine3 =[ $paine3, ogre_paine4 ] {ai_pain(9);};
|
||||
void() ogre_paine4 =[ $paine4, ogre_paine5 ] {ai_pain(4);};
|
||||
void() ogre_paine5 =[ $paine5, ogre_paine6 ] {};
|
||||
void() ogre_paine6 =[ $paine6, ogre_paine7 ] {};
|
||||
void() ogre_paine7 =[ $paine7, ogre_paine8 ] {};
|
||||
void() ogre_paine8 =[ $paine8, ogre_paine9 ] {};
|
||||
void() ogre_paine9 =[ $paine9, ogre_paine10] {};
|
||||
void() ogre_paine10=[ $paine10, ogre_paine11] {};
|
||||
void() ogre_paine11=[ $paine11, ogre_paine12] {};
|
||||
void() ogre_paine12=[ $paine12, ogre_paine13] {};
|
||||
void() ogre_paine13=[ $paine13, ogre_paine14] {};
|
||||
void() ogre_paine14=[ $paine14, ogre_paine15] {};
|
||||
void() ogre_paine15=[ $paine15, ogre_run1 ] {};
|
||||
|
||||
/*==========
|
||||
ogre_pain
|
||||
==========*/
|
||||
void(entity attacker, float damage) ogre_pain =
|
||||
{
|
||||
if (self.pain_finished > time)
|
||||
return;
|
||||
sound (self, CHAN_VOICE, "ogre/ogpain1.wav", 1, ATTN_NORM);
|
||||
|
||||
float r = randomrange(4);
|
||||
if (r == 0)
|
||||
{
|
||||
ogre_pain1 ();
|
||||
self.pain_finished = time + 1;
|
||||
}
|
||||
else if (r == 1)
|
||||
{
|
||||
ogre_painb1 ();
|
||||
self.pain_finished = time + 1;
|
||||
}
|
||||
else if (r == 2)
|
||||
{
|
||||
ogre_painc1 ();
|
||||
self.pain_finished = time + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = random();
|
||||
if (r < 0.5)
|
||||
{
|
||||
ogre_paind1 ();
|
||||
self.pain_finished = time + 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ogre_paine1 ();
|
||||
self.pain_finished = time + 2;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void() ogre_die1 =[ $death1, ogre_die2 ] {};
|
||||
void() ogre_die2 =[ $death2, ogre_die3 ] {};
|
||||
void() ogre_die3 =[ $death3, ogre_die4 ] {DropBackpack();};
|
||||
void() ogre_die4 =[ $death4, ogre_die5 ] {};
|
||||
void() ogre_die5 =[ $death5, ogre_die6 ] {};
|
||||
void() ogre_die6 =[ $death6, ogre_die7 ] {};
|
||||
void() ogre_die7 =[ $death7, ogre_die8 ] {};
|
||||
void() ogre_die8 =[ $death8, ogre_die9 ] {};
|
||||
void() ogre_die9 =[ $death9, ogre_die10 ] {};
|
||||
void() ogre_die10 =[ $death10, ogre_die11 ] {};
|
||||
void() ogre_die11 =[ $death11, ogre_die12 ] {};
|
||||
void() ogre_die12 =[ $death12, ogre_die13 ] {};
|
||||
void() ogre_die13 =[ $death13, ogre_die14 ] {};
|
||||
void() ogre_die14 =[ $death14, ogre_die14 ] {};
|
||||
|
||||
void() ogre_bdie1 =[ $bdeath1, ogre_bdie2 ] {};
|
||||
void() ogre_bdie2 =[ $bdeath2, ogre_bdie3 ] {ai_forward(5);};
|
||||
void() ogre_bdie3 =[ $bdeath3, ogre_bdie4 ] {DropBackpack();};
|
||||
void() ogre_bdie4 =[ $bdeath4, ogre_bdie5 ] {ai_forward(1);};
|
||||
void() ogre_bdie5 =[ $bdeath5, ogre_bdie6 ] {ai_forward(3);};
|
||||
void() ogre_bdie6 =[ $bdeath6, ogre_bdie7 ] {ai_forward(7);};
|
||||
void() ogre_bdie7 =[ $bdeath7, ogre_bdie8 ] {ai_forward(25);};
|
||||
void() ogre_bdie8 =[ $bdeath8, ogre_bdie9 ] {};
|
||||
void() ogre_bdie9 =[ $bdeath9, ogre_bdie10 ] {};
|
||||
void() ogre_bdie10 =[ $bdeath10, ogre_bdie10 ] {};
|
||||
|
||||
/*==========
|
||||
ogre_die
|
||||
==========*/
|
||||
void(entity inflictor, entity attacker) ogre_die =
|
||||
{
|
||||
if (self.health < -80)
|
||||
{
|
||||
SpawnGib ("progs/gib3.mdl");
|
||||
SpawnGib ("progs/gib3.mdl");
|
||||
SpawnGib ("progs/gib3.mdl");
|
||||
SpawnGib ("progs/gib4.mdl");
|
||||
SpawnGib ("progs/gib5.mdl");
|
||||
SpawnGib ("progs/blood.mdl");
|
||||
SpawnGib ("progs/blood.mdl");
|
||||
BecomeGibs ();
|
||||
return;
|
||||
}
|
||||
|
||||
self.solid = SOLID_NOT;
|
||||
sound (self, CHAN_VOICE, "ogre/ogdth.wav", 1, ATTN_NORM);
|
||||
if (random() < 0.5)
|
||||
ogre_die1 ();
|
||||
else
|
||||
ogre_bdie1 ();
|
||||
};
|
||||
|
||||
/*QUAKED monster_ogre (1 0 0) (-32 -32 -24) (32 32 64) Ambush
|
||||
{
|
||||
model ("progs/ogre.mdl");
|
||||
}
|
||||
Ogre.
|
||||
*/
|
||||
void() monster_ogre =
|
||||
{
|
||||
if (deathmatch)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
precache_model ("progs/ogre.mdl");
|
||||
precache_model ("progs/h_ogre.mdl");
|
||||
precache_model ("progs/grenade.mdl");
|
||||
|
||||
precache_sound ("ogre/ogdrag.wav");
|
||||
precache_sound ("ogre/ogdth.wav");
|
||||
precache_sound ("ogre/ogidle.wav");
|
||||
precache_sound ("ogre/ogidle2.wav");
|
||||
precache_sound ("ogre/ogpain1.wav");
|
||||
precache_sound ("ogre/ogsawatk.wav");
|
||||
precache_sound ("ogre/ogwake.wav");
|
||||
|
||||
self.th_stand = ogre_stand1;
|
||||
self.th_walk = ogre_walk1;
|
||||
self.th_run = ogre_run1;
|
||||
self.th_die = ogre_die;
|
||||
self.th_melee = ogre_melee;
|
||||
self.th_missile = ogre_grenade1;
|
||||
self.th_spam = ogre_spam1;
|
||||
self.th_pain = ogre_pain;
|
||||
|
||||
if (random() < 0.3)
|
||||
self.skin = 1;
|
||||
self.ammo_rockets = 2;
|
||||
|
||||
monster_start("progs/ogre.mdl", "progs/h_ogre.mdl", 200, 0, VEC_HULL2_MIN, VEC_HULL2_MAX);
|
||||
};
|
||||
|
||||
/*==========
|
||||
monster_ogre_marksman
|
||||
For compatibility only.
|
||||
==========*/
|
||||
void() monster_ogre_marksman =
|
||||
{
|
||||
self.classname = "monster_ogre";
|
||||
monster_ogre ();
|
||||
};
|
||||
241
mod_slipgate/source/server/monsters/oldone.qc
Normal file
241
mod_slipgate/source/server/monsters/oldone.qc
Normal file
@@ -0,0 +1,241 @@
|
||||
$frame old1 old2 old3 old4 old5 old6 old7 old8 old9
|
||||
$frame old10 old11 old12 old13 old14 old15 old16 old17 old18 old19
|
||||
$frame old20 old21 old22 old23 old24 old25 old26 old27 old28 old29
|
||||
$frame old30 old31 old32 old33 old34 old35 old36 old37 old38 old39
|
||||
$frame old40 old41 old42 old43 old44 old45 old46
|
||||
|
||||
$frame shake1 shake2 shake3 shake4 shake5 shake6 shake7 shake8
|
||||
$frame shake9 shake10 shake11 shake12 shake13 shake14
|
||||
$frame shake15 shake16 shake17 shake18 shake19 shake20 shake21
|
||||
|
||||
entity shub;
|
||||
|
||||
/*==========
|
||||
shub_awake
|
||||
==========*/
|
||||
void() shub_awake =
|
||||
{
|
||||
self.frame = self.frame + 1;
|
||||
if (self.frame > $old46)
|
||||
self.frame = $old1;
|
||||
|
||||
self.think = shub_awake;
|
||||
self.nextthink = time + 0.1;
|
||||
|
||||
if (time < self.attack_finished)
|
||||
return;
|
||||
sound(self, CHAN_VOICE, "boss2/idle.wav", 1, ATTN_IDLE);
|
||||
self.attack_finished = time + 2 + random() * 2;
|
||||
};
|
||||
|
||||
/*==========
|
||||
shub_idle
|
||||
==========*/
|
||||
void() shub_idle =
|
||||
{
|
||||
self.frame = self.frame + 1;
|
||||
if (self.frame > $old46)
|
||||
self.frame = $old1;
|
||||
|
||||
// look for a player
|
||||
entity client = checkclient();
|
||||
if (client)
|
||||
{
|
||||
if (visible(client))
|
||||
{
|
||||
self.enemy = client;
|
||||
sound(self, CHAN_BODY, "boss2/sight.wav", 1, ATTN_NONE); // no attenuation
|
||||
self.attack_finished = time + 3;
|
||||
self.think = shub_awake;
|
||||
self.nextthink = time + 0.1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.think = shub_idle;
|
||||
self.nextthink = time + 0.1;
|
||||
};
|
||||
|
||||
/*==========
|
||||
shub_finale_3
|
||||
==========*/
|
||||
void() shub_finale_3 =
|
||||
{
|
||||
// switch cd track
|
||||
WriteByte (MSG_ALL, SVC_CDTRACK);
|
||||
WriteByte (MSG_ALL, 3);
|
||||
WriteByte (MSG_ALL, 3);
|
||||
|
||||
// turn lights back on and spawn a load of gibs
|
||||
lightstyle (0, "m");
|
||||
sound (self, CHAN_VOICE, "boss2/pop2.wav", 1, ATTN_NONE); // no attenuation
|
||||
for (float i = 0; i < 20; i++)
|
||||
{
|
||||
SpawnGib("progs/gib3.mdl");
|
||||
SpawnGib("progs/gib4.mdl");
|
||||
SpawnGib("progs/gib5.mdl");
|
||||
SpawnGib("progs/blood.mdl");
|
||||
}
|
||||
|
||||
// start the end text
|
||||
WriteByte (MSG_ALL, SVC_FINALE);
|
||||
WriteString (MSG_ALL, "Congratulations and well done! You have\nbeaten the hideous Shub-Niggurath, and\nher hundreds of ugly changelings and\nmonsters. You have proven that your\nskill and your cunning are greater than\nall the powers of Quake. You are the\nmaster now. Id Software salutes you.");
|
||||
|
||||
// find the intermission spot
|
||||
entity pos = find (world, classname, "info_intermission");
|
||||
if (!pos)
|
||||
error ("no info_intermission");
|
||||
|
||||
// put a player model down and face it towards the intermission spot
|
||||
entity p = spawn();
|
||||
p.solid = SOLID_NOT;
|
||||
p.movetype = MOVETYPE_NONE;
|
||||
setmodel (p, "progs/dplayer.mdl");
|
||||
makevectors(self.angles);
|
||||
setorigin (p, self.origin + v_forward * 128);
|
||||
p.angles_y = vectoyaw(pos.origin - p.origin);
|
||||
|
||||
// remove shub
|
||||
remove (self);
|
||||
};
|
||||
|
||||
void() shub_thrash1 =[ $shake1, shub_thrash2 ] {lightstyle(0, "m");};
|
||||
void() shub_thrash2 =[ $shake2, shub_thrash3 ] {lightstyle(0, "k");};
|
||||
void() shub_thrash3 =[ $shake3, shub_thrash4 ] {lightstyle(0, "k");};
|
||||
void() shub_thrash4 =[ $shake4, shub_thrash5 ] {lightstyle(0, "i");};
|
||||
void() shub_thrash5 =[ $shake5, shub_thrash6 ] {lightstyle(0, "g");};
|
||||
void() shub_thrash6 =[ $shake6, shub_thrash7 ] {lightstyle(0, "e");};
|
||||
void() shub_thrash7 =[ $shake7, shub_thrash8 ] {lightstyle(0, "c");};
|
||||
void() shub_thrash8 =[ $shake8, shub_thrash9 ] {lightstyle(0, "a");};
|
||||
void() shub_thrash9 =[ $shake9, shub_thrash10 ] {lightstyle(0, "c");};
|
||||
void() shub_thrash10 =[ $shake10, shub_thrash11 ] {lightstyle(0, "e");};
|
||||
void() shub_thrash11 =[ $shake11, shub_thrash12 ] {lightstyle(0, "g");};
|
||||
void() shub_thrash12 =[ $shake12, shub_thrash13 ] {lightstyle(0, "i");};
|
||||
void() shub_thrash13 =[ $shake13, shub_thrash14 ] {lightstyle(0, "k");};
|
||||
void() shub_thrash14 =[ $shake14, shub_thrash15 ] {lightstyle(0, "m");};
|
||||
void() shub_thrash15 =[ $shake15, shub_thrash16 ]
|
||||
{
|
||||
lightstyle(0, "m");
|
||||
self.count = self.count + 1;
|
||||
if (self.count < 3)
|
||||
self.think = shub_thrash1;
|
||||
};
|
||||
void() shub_thrash16 =[ $shake16, shub_thrash17 ] {lightstyle(0, "g");};
|
||||
void() shub_thrash17 =[ $shake17, shub_thrash18 ] {lightstyle(0, "c");};
|
||||
void() shub_thrash18 =[ $shake18, shub_thrash19 ] {lightstyle(0, "b");};
|
||||
void() shub_thrash19 =[ $shake19, shub_thrash20 ] {lightstyle(0, "a");};
|
||||
void() shub_thrash20 =[ $shake20, shub_thrash21 ] {lightstyle(0, "a");};
|
||||
void() shub_thrash21 =[ $shake21, shub_thrash21 ] {shub_finale_3();};
|
||||
|
||||
/*==========
|
||||
shub_finale_3
|
||||
==========*/
|
||||
void() shub_finale_2 =
|
||||
{
|
||||
shub.think = shub_thrash1;
|
||||
sound(shub, CHAN_VOICE, "boss2/death.wav", 1, ATTN_NONE); // no attenuation
|
||||
remove(self);
|
||||
};
|
||||
|
||||
/*==========
|
||||
shub_finale_2
|
||||
==========*/
|
||||
void() shub_finale_1 =
|
||||
{
|
||||
// start a teleport splash inside shub
|
||||
te_teleport(shub.origin + [0, 0, 192]);
|
||||
sound(shub, CHAN_VOICE, "misc/r_tele1.wav", 1, ATTN_NONE); // no attenuation
|
||||
|
||||
// wait for 2 seconds
|
||||
self.nextthink = time + 2;
|
||||
self.think = shub_finale_2;
|
||||
};
|
||||
|
||||
/*==========
|
||||
shub_die
|
||||
==========*/
|
||||
void(entity inflictor, entity attacker) shub_die =
|
||||
{
|
||||
// bump the kill counter
|
||||
killed_monsters = killed_monsters + 1;
|
||||
WriteByte (MSG_ALL, SVC_KILLEDMONSTER);
|
||||
|
||||
// put up the end of level scoreboard
|
||||
intermission_running = 1;
|
||||
intermission_exittime = -1;
|
||||
WriteByte (MSG_ALL, SVC_INTERMISSION);
|
||||
|
||||
// find the intermission spot
|
||||
entity pos = find (world, classname, "info_intermission");
|
||||
if (!pos)
|
||||
error("no info_intermission");
|
||||
|
||||
// move all players to the intermission spot
|
||||
entity p = find (world, classname, "player");
|
||||
while (p != world)
|
||||
{
|
||||
p.view_ofs = '0 0 0';
|
||||
p.angles = other.v_angle = pos.mangle;
|
||||
p.fixangle = TRUE;
|
||||
p.think = SUB_Null;
|
||||
p.nextthink = time + 0.1;
|
||||
p.takedamage = DAMAGE_NO;
|
||||
p.solid = SOLID_NOT;
|
||||
p.movetype = MOVETYPE_NONE;
|
||||
p.modelindex = 0;
|
||||
setorigin(p, pos.origin);
|
||||
p = find(p, classname, "player");
|
||||
}
|
||||
|
||||
// wait for 1 second
|
||||
entity timer = spawn();
|
||||
timer.think = shub_finale_1;
|
||||
timer.nextthink = time + 1;
|
||||
};
|
||||
|
||||
/*==========
|
||||
shub_pain
|
||||
==========*/
|
||||
void (entity attacker, float damage) shub_pain =
|
||||
{
|
||||
self.health = 40000;
|
||||
};
|
||||
|
||||
/*QUAKED monster_oldone (1 0 0) (-160 -128 -24) (128 128 256)
|
||||
{ model ("progs/oldone.mdl"); }
|
||||
Shub-Niggurath.
|
||||
*/
|
||||
void() monster_oldone =
|
||||
{
|
||||
if (deathmatch)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
|
||||
precache_model2 ("progs/oldone.mdl");
|
||||
precache_model ("progs/dplayer.mdl");
|
||||
|
||||
precache_sound2 ("boss2/death.wav");
|
||||
precache_sound2 ("boss2/idle.wav");
|
||||
precache_sound2 ("boss2/sight.wav");
|
||||
precache_sound2 ("boss2/pop2.wav");
|
||||
|
||||
self.solid = SOLID_SLIDEBOX;
|
||||
self.movetype = MOVETYPE_STEP;
|
||||
|
||||
setmodel (self, "progs/oldone.mdl");
|
||||
setsize (self, '-160 -128 -24', '160 128 256');
|
||||
|
||||
self.health = 40000; // kill by telefrag
|
||||
self.takedamage = DAMAGE_YES;
|
||||
self.th_pain = shub_pain;
|
||||
self.th_die = shub_die;
|
||||
|
||||
shub = self;
|
||||
total_monsters = total_monsters + 1;
|
||||
|
||||
self.think = shub_idle;
|
||||
self.nextthink = time + 0.1;
|
||||
};
|
||||
|
||||
229
mod_slipgate/source/server/monsters/shalrath.qc
Normal file
229
mod_slipgate/source/server/monsters/shalrath.qc
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
SHAL-RATH
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
$cd id1/models/shalrath
|
||||
$origin 0 0 24
|
||||
$base base
|
||||
$skin skin
|
||||
$scale 0.7
|
||||
|
||||
$frame attack1 attack2 attack3 attack4 attack5 attack6 attack7 attack8
|
||||
$frame attack9 attack10 attack11
|
||||
|
||||
$frame pain1 pain2 pain3 pain4 pain5
|
||||
|
||||
$frame death1 death2 death3 death4 death5 death6 death7
|
||||
|
||||
$frame idle1 idle2 idle3 idle4 idle5 idle6 idle7 idle8 idle9
|
||||
|
||||
$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8 walk9 walk10
|
||||
$frame walk11 walk12
|
||||
|
||||
void(entity attacker, float damage) shalrath_pain;
|
||||
|
||||
void() ShalMissile;
|
||||
|
||||
void() shal_stand1 =[ $idle1, shal_stand2 ] {ai_stand();};
|
||||
void() shal_stand2 =[ $idle2, shal_stand3 ] {ai_stand();};
|
||||
void() shal_stand3 =[ $idle3, shal_stand4 ] {ai_stand();};
|
||||
void() shal_stand4 =[ $idle4, shal_stand5 ] {ai_stand();};
|
||||
void() shal_stand5 =[ $idle5, shal_stand6 ] {ai_stand();};
|
||||
void() shal_stand6 =[ $idle6, shal_stand7 ] {ai_stand();};
|
||||
void() shal_stand7 =[ $idle7, shal_stand8 ] {ai_stand();};
|
||||
void() shal_stand8 =[ $idle8, shal_stand9 ] {ai_stand();};
|
||||
void() shal_stand9 =[ $idle9, shal_stand1 ] {ai_stand();};
|
||||
|
||||
void() shal_walk1 =[ $walk1, shal_walk2 ] {ai_walk(5);};
|
||||
void() shal_walk2 =[ $walk2, shal_walk3 ] {if (random() < 0.2) sound (self, CHAN_VOICE, "shalrath/idle.wav", 1, ATTN_IDLE);ai_walk(6);};
|
||||
void() shal_walk3 =[ $walk3, shal_walk4 ] {ai_walk(4);};
|
||||
void() shal_walk4 =[ $walk4, shal_walk5 ] {ai_walk(0);};
|
||||
void() shal_walk5 =[ $walk5, shal_walk6 ] {ai_walk(0);};
|
||||
void() shal_walk6 =[ $walk6, shal_walk7 ] {ai_walk(0);};
|
||||
void() shal_walk7 =[ $walk7, shal_walk8 ] {ai_walk(0);};
|
||||
void() shal_walk8 =[ $walk8, shal_walk9 ] {ai_walk(5);};
|
||||
void() shal_walk9 =[ $walk9, shal_walk10 ] {ai_walk(6);};
|
||||
void() shal_walk10 =[ $walk10, shal_walk11 ] {ai_walk(5);};
|
||||
void() shal_walk11 =[ $walk11, shal_walk12 ] {ai_walk(0);};
|
||||
void() shal_walk12 =[ $walk12, shal_walk1 ] {ai_walk(4);};
|
||||
|
||||
void() shal_run1 =[ $walk1, shal_run2 ] {ai_run(5);};
|
||||
void() shal_run2 =[ $walk2, shal_run3 ] {
|
||||
if (random() < 0.2)
|
||||
sound (self, CHAN_VOICE, "shalrath/idle.wav", 1, ATTN_IDLE);
|
||||
ai_run(6);};
|
||||
void() shal_run3 =[ $walk3, shal_run4 ] {ai_run(4);};
|
||||
void() shal_run4 =[ $walk4, shal_run5 ] {ai_run(0);};
|
||||
void() shal_run5 =[ $walk5, shal_run6 ] {ai_run(0);};
|
||||
void() shal_run6 =[ $walk6, shal_run7 ] {ai_run(0);};
|
||||
void() shal_run7 =[ $walk7, shal_run8 ] {ai_run(0);};
|
||||
void() shal_run8 =[ $walk8, shal_run9 ] {ai_run(5);};
|
||||
void() shal_run9 =[ $walk9, shal_run10 ] {ai_run(6);};
|
||||
void() shal_run10 =[ $walk10, shal_run11 ] {ai_run(5);};
|
||||
void() shal_run11 =[ $walk11, shal_run12 ] {ai_run(0);};
|
||||
void() shal_run12 =[ $walk12, shal_run1 ] {ai_run(4);};
|
||||
|
||||
|
||||
void() shal_attack1 =[ $attack1, shal_attack2 ] {
|
||||
sound (self, CHAN_VOICE, "shalrath/attack.wav", 1, ATTN_NORM);
|
||||
ai_face();
|
||||
};
|
||||
void() shal_attack2 =[ $attack2, shal_attack3 ] {ai_face();};
|
||||
void() shal_attack3 =[ $attack3, shal_attack4 ] {ai_face();};
|
||||
void() shal_attack4 =[ $attack4, shal_attack5 ] {ai_face();};
|
||||
void() shal_attack5 =[ $attack5, shal_attack6 ] {ai_face();};
|
||||
void() shal_attack6 =[ $attack6, shal_attack7 ] {ai_face();};
|
||||
void() shal_attack7 =[ $attack7, shal_attack8 ] {ai_face();};
|
||||
void() shal_attack8 =[ $attack8, shal_attack9 ] {ai_face();};
|
||||
void() shal_attack9 =[ $attack9, shal_attack10 ] {ShalMissile();};
|
||||
void() shal_attack10 =[ $attack10, shal_attack11 ] {ai_face();};
|
||||
void() shal_attack11 =[ $attack11, shal_run1 ] {};
|
||||
|
||||
void() shal_pain1 =[ $pain1, shal_pain2 ] {};
|
||||
void() shal_pain2 =[ $pain2, shal_pain3 ] {};
|
||||
void() shal_pain3 =[ $pain3, shal_pain4 ] {};
|
||||
void() shal_pain4 =[ $pain4, shal_pain5 ] {};
|
||||
void() shal_pain5 =[ $pain5, shal_run1 ] {};
|
||||
|
||||
void() shal_death1 =[ $death1, shal_death2 ] {};
|
||||
void() shal_death2 =[ $death2, shal_death3 ] {};
|
||||
void() shal_death3 =[ $death3, shal_death4 ] {};
|
||||
void() shal_death4 =[ $death4, shal_death5 ] {};
|
||||
void() shal_death5 =[ $death5, shal_death6 ] {};
|
||||
void() shal_death6 =[ $death6, shal_death7 ] {};
|
||||
void() shal_death7 =[ $death7, shal_death7 ] {};
|
||||
|
||||
void(entity attacker, float damage) shalrath_pain =
|
||||
{
|
||||
if (self.pain_finished > time)
|
||||
return;
|
||||
sound (self, CHAN_VOICE, "shalrath/pain.wav", 1, ATTN_NORM);
|
||||
self.pain_finished = time + 3;
|
||||
shal_pain1();
|
||||
};
|
||||
|
||||
void(entity inflictor, entity attacker) shalrath_die =
|
||||
{
|
||||
// check for gib
|
||||
if (self.health < -90)
|
||||
{
|
||||
SpawnGib("progs/gib1.mdl");
|
||||
SpawnGib("progs/gib2.mdl");
|
||||
SpawnGib("progs/gib3.mdl");
|
||||
SpawnGib("progs/gib4.mdl");
|
||||
SpawnGib("progs/gib5.mdl");
|
||||
SpawnGib("progs/blood.mdl");
|
||||
SpawnGib("progs/blood.mdl");
|
||||
BecomeGibs();
|
||||
return;
|
||||
}
|
||||
|
||||
// regular death
|
||||
sound (self, CHAN_VOICE, "shalrath/death.wav", 1, ATTN_NORM);
|
||||
self.solid = SOLID_NOT;
|
||||
shal_death1();
|
||||
};
|
||||
|
||||
/*
|
||||
================
|
||||
ShalMissile
|
||||
================
|
||||
*/
|
||||
void() ShalMissileTouch;
|
||||
void() ShalHome;
|
||||
void() ShalMissile =
|
||||
{
|
||||
local entity missile;
|
||||
local vector dir;
|
||||
local float dist, flytime;
|
||||
|
||||
dir = normalize((self.enemy.origin + '0 0 10') - self.origin);
|
||||
dist = vlen (self.enemy.origin - self.origin);
|
||||
flytime = dist * 0.002;
|
||||
if (flytime < 0.1)
|
||||
flytime = 0.1;
|
||||
|
||||
self.effects = self.effects | EF_MUZZLEFLASH;
|
||||
sound (self, CHAN_WEAPON, "shalrath/attack2.wav", 1, ATTN_NORM);
|
||||
|
||||
missile = spawn ();
|
||||
missile.owner = self;
|
||||
|
||||
missile.solid = SOLID_BBOX;
|
||||
missile.movetype = MOVETYPE_FLYMISSILE;
|
||||
setmodel (missile, "progs/v_spike.mdl");
|
||||
setsize (missile, '0 0 0', '0 0 0');
|
||||
|
||||
missile.origin = self.origin + '0 8 20';
|
||||
missile.velocity = dir * 400;
|
||||
missile.avelocity = '300 300 300';
|
||||
|
||||
missile.think = ShalHome;
|
||||
missile.nextthink = time + flytime;
|
||||
|
||||
missile.enemy = self.enemy;
|
||||
missile.touch = ShalMissileTouch;
|
||||
};
|
||||
|
||||
void() ShalHome =
|
||||
{
|
||||
if (self.enemy.health <= 0)
|
||||
return;
|
||||
if (self.owner.health <= 0 && skill < 2)
|
||||
return;
|
||||
|
||||
vector dir = normalize(self.enemy.origin + '0 0 10' - self.origin);
|
||||
if (skill == 3)
|
||||
self.velocity = dir * 350;
|
||||
else
|
||||
self.velocity = dir * 250;
|
||||
|
||||
self.nextthink = time + 0.2;
|
||||
self.think = ShalHome;
|
||||
};
|
||||
|
||||
void() ShalMissileTouch =
|
||||
{
|
||||
RadiusDamage (self, self.owner, 40, world);
|
||||
te_tarexplosion(self.origin);
|
||||
remove(self);
|
||||
};
|
||||
|
||||
//=================================================================
|
||||
|
||||
/*QUAKED monster_shalrath (1 0 0) (-32 -32 -24) (32 32 48) Ambush
|
||||
{
|
||||
model ({ "path" : "progs/shalrath.mdl", "frame": 23 });
|
||||
}
|
||||
Vore.
|
||||
*/
|
||||
void() monster_shalrath =
|
||||
{
|
||||
if (deathmatch)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
precache_model2 ("progs/shalrath.mdl");
|
||||
precache_model2 ("progs/h_shal.mdl");
|
||||
precache_model2 ("progs/v_spike.mdl");
|
||||
|
||||
precache_sound2 ("shalrath/attack.wav");
|
||||
precache_sound2 ("shalrath/attack2.wav");
|
||||
precache_sound2 ("shalrath/death.wav");
|
||||
precache_sound2 ("shalrath/idle.wav");
|
||||
precache_sound2 ("shalrath/pain.wav");
|
||||
precache_sound2 ("shalrath/sight.wav");
|
||||
|
||||
self.th_stand = shal_stand1;
|
||||
self.th_walk = shal_walk1;
|
||||
self.th_run = shal_run1;
|
||||
self.th_die = shalrath_die;
|
||||
self.th_pain = shalrath_pain;
|
||||
self.th_missile = shal_attack1;
|
||||
|
||||
monster_start("progs/shalrath.mdl", "progs/h_shal.mdl", 400, 0, VEC_HULL2_MIN, VEC_HULL2_MAX);
|
||||
};
|
||||
352
mod_slipgate/source/server/monsters/shambler.qc
Normal file
352
mod_slipgate/source/server/monsters/shambler.qc
Normal file
@@ -0,0 +1,352 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
SHAMBLER
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
$cd id1/models/shams
|
||||
$origin 0 0 24
|
||||
$base base
|
||||
$skin base
|
||||
|
||||
$frame stand1 stand2 stand3 stand4 stand5 stand6 stand7 stand8 stand9
|
||||
$frame stand10 stand11 stand12 stand13 stand14 stand15 stand16 stand17
|
||||
|
||||
$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7
|
||||
$frame walk8 walk9 walk10 walk11 walk12
|
||||
|
||||
$frame run1 run2 run3 run4 run5 run6
|
||||
|
||||
$frame smash1 smash2 smash3 smash4 smash5 smash6 smash7
|
||||
$frame smash8 smash9 smash10 smash11 smash12
|
||||
|
||||
$frame swingr1 swingr2 swingr3 swingr4 swingr5
|
||||
$frame swingr6 swingr7 swingr8 swingr9
|
||||
|
||||
$frame swingl1 swingl2 swingl3 swingl4 swingl5
|
||||
$frame swingl6 swingl7 swingl8 swingl9
|
||||
|
||||
$frame magic1 magic2 magic3 magic4 magic5
|
||||
$frame magic6 magic7 magic8 magic9 magic10 magic11 magic12
|
||||
|
||||
$frame pain1 pain2 pain3 pain4 pain5 pain6
|
||||
|
||||
$frame death1 death2 death3 death4 death5 death6
|
||||
$frame death7 death8 death9 death10 death11
|
||||
|
||||
void() sham_stand1 =[ $stand1, sham_stand2 ] {ai_stand();};
|
||||
void() sham_stand2 =[ $stand2, sham_stand3 ] {ai_stand();};
|
||||
void() sham_stand3 =[ $stand3, sham_stand4 ] {ai_stand();};
|
||||
void() sham_stand4 =[ $stand4, sham_stand5 ] {ai_stand();};
|
||||
void() sham_stand5 =[ $stand5, sham_stand6 ] {ai_stand();};
|
||||
void() sham_stand6 =[ $stand6, sham_stand7 ] {ai_stand();};
|
||||
void() sham_stand7 =[ $stand7, sham_stand8 ] {ai_stand();};
|
||||
void() sham_stand8 =[ $stand8, sham_stand9 ] {ai_stand();};
|
||||
void() sham_stand9 =[ $stand9, sham_stand10] {ai_stand();};
|
||||
void() sham_stand10 =[ $stand10, sham_stand11] {ai_stand();};
|
||||
void() sham_stand11 =[ $stand11, sham_stand12] {ai_stand();};
|
||||
void() sham_stand12 =[ $stand12, sham_stand13] {ai_stand();};
|
||||
void() sham_stand13 =[ $stand13, sham_stand14] {ai_stand();};
|
||||
void() sham_stand14 =[ $stand14, sham_stand15] {ai_stand();};
|
||||
void() sham_stand15 =[ $stand15, sham_stand16] {ai_stand();};
|
||||
void() sham_stand16 =[ $stand16, sham_stand17] {ai_stand();};
|
||||
void() sham_stand17 =[ $stand17, sham_stand1 ] {ai_stand();};
|
||||
|
||||
void() sham_walk1 =[ $walk1, sham_walk2 ] {ai_walk(10);};
|
||||
void() sham_walk2 =[ $walk2, sham_walk3 ] {ai_walk(9);};
|
||||
void() sham_walk3 =[ $walk3, sham_walk4 ] {ai_walk(9);};
|
||||
void() sham_walk4 =[ $walk4, sham_walk5 ] {ai_walk(5);};
|
||||
void() sham_walk5 =[ $walk5, sham_walk6 ] {ai_walk(6);};
|
||||
void() sham_walk6 =[ $walk6, sham_walk7 ] {ai_walk(12);};
|
||||
void() sham_walk7 =[ $walk7, sham_walk8 ] {ai_walk(8);};
|
||||
void() sham_walk8 =[ $walk8, sham_walk9 ] {ai_walk(3);};
|
||||
void() sham_walk9 =[ $walk9, sham_walk10] {ai_walk(13);};
|
||||
void() sham_walk10 =[ $walk10, sham_walk11] {ai_walk(9);};
|
||||
void() sham_walk11 =[ $walk11, sham_walk12] {ai_walk(7);};
|
||||
void() sham_walk12 =[ $walk12, sham_walk1 ] {ai_walk(7);
|
||||
if (random() > 0.8)
|
||||
sound (self, CHAN_VOICE, "shambler/sidle.wav", 1, ATTN_IDLE);};
|
||||
|
||||
void() sham_run1 =[ $run1, sham_run2 ] {ai_run(20);};
|
||||
void() sham_run2 =[ $run2, sham_run3 ] {ai_run(24);};
|
||||
void() sham_run3 =[ $run3, sham_run4 ] {ai_run(20);};
|
||||
void() sham_run4 =[ $run4, sham_run5 ] {ai_run(20);};
|
||||
void() sham_run5 =[ $run5, sham_run6 ] {ai_run(24);};
|
||||
void() sham_run6 =[ $run6, sham_run1 ] {ai_run(20);
|
||||
if (random() > 0.8)
|
||||
sound (self, CHAN_VOICE, "shambler/sidle.wav", 1, ATTN_IDLE);
|
||||
};
|
||||
|
||||
void() sham_smash1 =[ $smash1, sham_smash2 ] {
|
||||
sound (self, CHAN_VOICE, "shambler/melee1.wav", 1, ATTN_NORM);
|
||||
ai_charge(2);};
|
||||
void() sham_smash2 =[ $smash2, sham_smash3 ] {ai_charge(6);};
|
||||
void() sham_smash3 =[ $smash3, sham_smash4 ] {ai_charge(6);};
|
||||
void() sham_smash4 =[ $smash4, sham_smash5 ] {ai_charge(5);};
|
||||
void() sham_smash5 =[ $smash5, sham_smash6 ] {ai_charge(4);};
|
||||
void() sham_smash6 =[ $smash6, sham_smash7 ] {ai_charge(1);};
|
||||
void() sham_smash7 =[ $smash7, sham_smash8 ] {ai_charge(0);};
|
||||
void() sham_smash8 =[ $smash8, sham_smash9 ] {ai_charge(0);};
|
||||
void() sham_smash9 =[ $smash9, sham_smash10 ] {ai_charge(0);};
|
||||
void() sham_smash10 =[ $smash10, sham_smash11 ] {
|
||||
local vector delta;
|
||||
local float ldmg;
|
||||
|
||||
if (!self.enemy)
|
||||
return;
|
||||
ai_charge(0);
|
||||
|
||||
delta = self.enemy.origin - self.origin;
|
||||
|
||||
if (vlen(delta) > 100)
|
||||
return;
|
||||
if (!CanDamage (self.enemy, self))
|
||||
return;
|
||||
|
||||
ldmg = (random() + random() + random()) * 40;
|
||||
Damage (self.enemy, self, self, ldmg);
|
||||
sound (self, CHAN_VOICE, "shambler/smack.wav", 1, ATTN_NORM);
|
||||
|
||||
SpawnMeatSpray (self.origin + v_forward*16, crandom() * 100 * v_right);
|
||||
SpawnMeatSpray (self.origin + v_forward*16, crandom() * 100 * v_right);
|
||||
};
|
||||
void() sham_smash11 =[ $smash11, sham_smash12 ] {ai_charge(5);};
|
||||
void() sham_smash12 =[ $smash12, sham_run1 ] {ai_charge(4);};
|
||||
|
||||
void() sham_swingr1;
|
||||
|
||||
void(float side) ShamClaw =
|
||||
{
|
||||
local vector delta;
|
||||
local float ldmg;
|
||||
|
||||
if (!self.enemy)
|
||||
return;
|
||||
ai_charge(10);
|
||||
|
||||
delta = self.enemy.origin - self.origin;
|
||||
|
||||
if (vlen(delta) > 100)
|
||||
return;
|
||||
|
||||
ldmg = (random() + random() + random()) * 20;
|
||||
Damage (self.enemy, self, self, ldmg);
|
||||
sound (self, CHAN_VOICE, "shambler/smack.wav", 1, ATTN_NORM);
|
||||
|
||||
if (side)
|
||||
{
|
||||
makevectors (self.angles);
|
||||
SpawnMeatSpray (self.origin + v_forward*16, side * v_right);
|
||||
}
|
||||
};
|
||||
|
||||
void() sham_swingl1 =[ $swingl1, sham_swingl2 ] {
|
||||
sound (self, CHAN_VOICE, "shambler/melee2.wav", 1, ATTN_NORM);
|
||||
ai_charge(5);};
|
||||
void() sham_swingl2 =[ $swingl2, sham_swingl3 ] {ai_charge(3);};
|
||||
void() sham_swingl3 =[ $swingl3, sham_swingl4 ] {ai_charge(7);};
|
||||
void() sham_swingl4 =[ $swingl4, sham_swingl5 ] {ai_charge(3);};
|
||||
void() sham_swingl5 =[ $swingl5, sham_swingl6 ] {ai_charge(7);};
|
||||
void() sham_swingl6 =[ $swingl6, sham_swingl7 ] {ai_charge(9);};
|
||||
void() sham_swingl7 =[ $swingl7, sham_swingl8 ] {ai_charge(5); ShamClaw(250);};
|
||||
void() sham_swingl8 =[ $swingl8, sham_swingl9 ] {ai_charge(4);};
|
||||
void() sham_swingl9 =[ $swingl9, sham_run1 ] {
|
||||
ai_charge(8);
|
||||
if (random()<0.5)
|
||||
self.think = sham_swingr1;
|
||||
};
|
||||
|
||||
void() sham_swingr1 =[ $swingr1, sham_swingr2 ] {
|
||||
sound (self, CHAN_VOICE, "shambler/melee1.wav", 1, ATTN_NORM);
|
||||
ai_charge(1);};
|
||||
void() sham_swingr2 =[ $swingr2, sham_swingr3 ] {ai_charge(8);};
|
||||
void() sham_swingr3 =[ $swingr3, sham_swingr4 ] {ai_charge(14);};
|
||||
void() sham_swingr4 =[ $swingr4, sham_swingr5 ] {ai_charge(7);};
|
||||
void() sham_swingr5 =[ $swingr5, sham_swingr6 ] {ai_charge(3);};
|
||||
void() sham_swingr6 =[ $swingr6, sham_swingr7 ] {ai_charge(6);};
|
||||
void() sham_swingr7 =[ $swingr7, sham_swingr8 ] {ai_charge(6); ShamClaw(-250);};
|
||||
void() sham_swingr8 =[ $swingr8, sham_swingr9 ] {ai_charge(3);};
|
||||
void() sham_swingr9 =[ $swingr9, sham_run1 ] {ai_charge(1);
|
||||
ai_charge(10);
|
||||
if (random()<0.5)
|
||||
self.think = sham_swingl1;
|
||||
};
|
||||
|
||||
void() sham_melee =
|
||||
{
|
||||
local float chance;
|
||||
|
||||
chance = random();
|
||||
if (chance > 0.6 || self.health == 600)
|
||||
sham_smash1 ();
|
||||
else if (chance > 0.3)
|
||||
sham_swingr1 ();
|
||||
else
|
||||
sham_swingl1 ();
|
||||
};
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
void() CastLightning =
|
||||
{
|
||||
local vector org, dir;
|
||||
|
||||
self.effects = self.effects | EF_MUZZLEFLASH;
|
||||
|
||||
ai_face ();
|
||||
|
||||
org = self.origin + '0 0 40';
|
||||
|
||||
dir = self.enemy.origin + '0 0 16' - org;
|
||||
dir = normalize (dir);
|
||||
|
||||
traceline (org, self.origin + dir*600, TRUE, self);
|
||||
|
||||
te_lightning1(org, trace_endpos, self);
|
||||
|
||||
LightningDamage (org, trace_endpos, self, 10);
|
||||
};
|
||||
|
||||
void() sham_magic1 =[ $magic1, sham_magic2 ] {ai_face();
|
||||
sound (self, CHAN_WEAPON, "shambler/sattck1.wav", 1, ATTN_NORM);
|
||||
};
|
||||
void() sham_magic2 =[ $magic2, sham_magic3 ] {ai_face();};
|
||||
void() sham_magic3 =[ $magic3, sham_magic4 ] {ai_face();self.nextthink = self.nextthink + 0.2;
|
||||
self.effects = self.effects | EF_MUZZLEFLASH;
|
||||
ai_face();
|
||||
self.aiment = spawn();
|
||||
setmodel (self.aiment, "progs/s_light.mdl");
|
||||
setorigin (self.aiment, self.origin);
|
||||
self.aiment.angles = self.angles;
|
||||
self.aiment.think = SUB_Remove;
|
||||
self.aiment.nextthink = time + 0.3;
|
||||
};
|
||||
void() sham_magic4 =[ $magic4, sham_magic5 ]
|
||||
{
|
||||
self.effects = self.effects | EF_MUZZLEFLASH;
|
||||
self.aiment.frame = 1;
|
||||
self.aiment.nextthink = time + 0.2;
|
||||
};
|
||||
void() sham_magic5 =[ $magic5, sham_magic6 ]
|
||||
{
|
||||
self.effects = self.effects | EF_MUZZLEFLASH;
|
||||
self.aiment.frame = 2;
|
||||
self.aiment.nextthink = time + 0.2;
|
||||
};
|
||||
void() sham_magic6 =[ $magic6, sham_magic9 ]
|
||||
{
|
||||
remove (self.aiment);
|
||||
CastLightning();
|
||||
sound (self, CHAN_WEAPON, "shambler/sboom.wav", 1, ATTN_NORM);
|
||||
};
|
||||
void() sham_magic9 =[ $magic9, sham_magic10 ]
|
||||
{CastLightning();};
|
||||
void() sham_magic10 =[ $magic10, sham_magic11 ]
|
||||
{CastLightning();};
|
||||
void() sham_magic11 =[ $magic11, sham_magic12 ]
|
||||
{
|
||||
if (skill == 3)
|
||||
CastLightning();
|
||||
};
|
||||
void() sham_magic12 =[ $magic12, sham_run1 ] {};
|
||||
|
||||
|
||||
|
||||
void() sham_pain1 =[ $pain1, sham_pain2 ] {};
|
||||
void() sham_pain2 =[ $pain2, sham_pain3 ] {};
|
||||
void() sham_pain3 =[ $pain3, sham_pain4 ] {};
|
||||
void() sham_pain4 =[ $pain4, sham_pain5 ] {};
|
||||
void() sham_pain5 =[ $pain5, sham_pain6 ] {};
|
||||
void() sham_pain6 =[ $pain6, sham_run1 ] {};
|
||||
|
||||
void(entity attacker, float damage) sham_pain =
|
||||
{
|
||||
if (random()*400 > damage)
|
||||
return;
|
||||
if (self.pain_finished > time)
|
||||
return;
|
||||
sound (self, CHAN_VOICE, "shambler/shurt2.wav", 1, ATTN_NORM);
|
||||
self.pain_finished = time + 2;
|
||||
sham_pain1();
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
void() sham_death1 =[ $death1, sham_death2 ] {};
|
||||
void() sham_death2 =[ $death2, sham_death3 ] {};
|
||||
void() sham_death3 =[ $death3, sham_death4 ] {};
|
||||
void() sham_death4 =[ $death4, sham_death5 ] {};
|
||||
void() sham_death5 =[ $death5, sham_death6 ] {};
|
||||
void() sham_death6 =[ $death6, sham_death7 ] {};
|
||||
void() sham_death7 =[ $death7, sham_death8 ] {};
|
||||
void() sham_death8 =[ $death8, sham_death9 ] {};
|
||||
void() sham_death9 =[ $death9, sham_death10 ] {};
|
||||
void() sham_death10 =[ $death10, sham_death11 ] {};
|
||||
void() sham_death11 =[ $death11, sham_death11 ] {};
|
||||
|
||||
void(entity inflictor, entity attacker) sham_die =
|
||||
{
|
||||
// check for gib
|
||||
if (self.health < -60)
|
||||
{
|
||||
SpawnGib("progs/gib3.mdl");
|
||||
SpawnGib("progs/gib3.mdl");
|
||||
SpawnGib("progs/gib3.mdl");
|
||||
SpawnGib("progs/gib4.mdl");
|
||||
SpawnGib("progs/gib5.mdl");
|
||||
SpawnGib("progs/blood.mdl");
|
||||
SpawnGib("progs/blood.mdl");
|
||||
BecomeGibs();
|
||||
return;
|
||||
}
|
||||
|
||||
// regular death
|
||||
self.solid = SOLID_NOT;
|
||||
sound(self, CHAN_VOICE, "shambler/sdeath.wav", 1, ATTN_NORM);
|
||||
sham_death1();
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
||||
/*QUAKED monster_shambler (1 0 0) (-32 -32 -24) (32 32 64) Ambush
|
||||
{
|
||||
model ("progs/shambler.mdl");
|
||||
}
|
||||
Shambler.
|
||||
*/
|
||||
void() monster_shambler =
|
||||
{
|
||||
if (deathmatch)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
precache_model ("progs/shambler.mdl");
|
||||
precache_model ("progs/s_light.mdl");
|
||||
precache_model ("progs/h_shams.mdl");
|
||||
precache_model ("progs/bolt.mdl");
|
||||
|
||||
precache_sound ("shambler/sattck1.wav");
|
||||
precache_sound ("shambler/sboom.wav");
|
||||
precache_sound ("shambler/sdeath.wav");
|
||||
precache_sound ("shambler/shurt2.wav");
|
||||
precache_sound ("shambler/sidle.wav");
|
||||
precache_sound ("shambler/ssight.wav");
|
||||
precache_sound ("shambler/melee1.wav");
|
||||
precache_sound ("shambler/melee2.wav");
|
||||
precache_sound ("shambler/smack.wav");
|
||||
|
||||
self.th_stand = sham_stand1;
|
||||
self.th_walk = sham_walk1;
|
||||
self.th_run = sham_run1;
|
||||
self.th_die = sham_die;
|
||||
self.th_melee = sham_melee;
|
||||
self.th_missile = sham_magic1;
|
||||
self.th_pain = sham_pain;
|
||||
|
||||
monster_start("progs/shambler.mdl", "progs/h_shams.mdl", 600, 0, VEC_HULL2_MIN, VEC_HULL2_MAX);
|
||||
};
|
||||
244
mod_slipgate/source/server/monsters/soldier.qc
Normal file
244
mod_slipgate/source/server/monsters/soldier.qc
Normal file
@@ -0,0 +1,244 @@
|
||||
$frame stand1 stand2 stand3 stand4 stand5 stand6 stand7 stand8
|
||||
|
||||
$frame death1 death2 death3 death4 death5 death6 death7 death8
|
||||
$frame death9 death10
|
||||
|
||||
$frame deathc1 deathc2 deathc3 deathc4 deathc5 deathc6 deathc7 deathc8
|
||||
$frame deathc9 deathc10 deathc11
|
||||
|
||||
$frame load1 load2 load3 load4 load5 load6 load7 load8 load9 load10 load11
|
||||
|
||||
$frame pain1 pain2 pain3 pain4 pain5 pain6
|
||||
|
||||
$frame painb1 painb2 painb3 painb4 painb5 painb6 painb7 painb8 painb9 painb10
|
||||
$frame painb11 painb12 painb13 painb14
|
||||
|
||||
$frame painc1 painc2 painc3 painc4 painc5 painc6 painc7 painc8 painc9 painc10
|
||||
$frame painc11 painc12 painc13
|
||||
|
||||
$frame run1 run2 run3 run4 run5 run6 run7 run8
|
||||
|
||||
$frame shoot1 shoot2 shoot3 shoot4 shoot5 shoot6 shoot7 shoot8 shoot9
|
||||
|
||||
$frame prowl_1 prowl_2 prowl_3 prowl_4 prowl_5 prowl_6 prowl_7 prowl_8
|
||||
$frame prowl_9 prowl_10 prowl_11 prowl_12 prowl_13 prowl_14 prowl_15 prowl_16
|
||||
$frame prowl_17 prowl_18 prowl_19 prowl_20 prowl_21 prowl_22 prowl_23 prowl_24
|
||||
|
||||
|
||||
void() army_stand1 =[ $stand1, army_stand2 ] {
|
||||
if (random() < 0.1)
|
||||
sound (self, CHAN_VOICE, "soldier/idle.wav", 1, ATTN_IDLE);
|
||||
ai_stand();};
|
||||
void() army_stand2 =[ $stand2, army_stand3 ] {ai_stand();};
|
||||
void() army_stand3 =[ $stand3, army_stand4 ] {ai_stand();};
|
||||
void() army_stand4 =[ $stand4, army_stand5 ] {ai_stand();};
|
||||
void() army_stand5 =[ $stand5, army_stand6 ] {ai_stand();};
|
||||
void() army_stand6 =[ $stand6, army_stand7 ] {ai_stand();};
|
||||
void() army_stand7 =[ $stand7, army_stand8 ] {ai_stand();};
|
||||
void() army_stand8 =[ $stand8, army_stand1 ] {ai_stand();};
|
||||
|
||||
void() army_walk1 =[ $prowl_1, army_walk2 ] {
|
||||
if (random() < 0.2)
|
||||
sound (self, CHAN_VOICE, "soldier/idle.wav", 1, ATTN_IDLE);
|
||||
ai_walk(1);};
|
||||
void() army_walk2 =[ $prowl_2, army_walk3 ] {ai_walk(1);};
|
||||
void() army_walk3 =[ $prowl_3, army_walk4 ] {ai_walk(1);};
|
||||
void() army_walk4 =[ $prowl_4, army_walk5 ] {ai_walk(1);};
|
||||
void() army_walk5 =[ $prowl_5, army_walk6 ] {ai_walk(2);};
|
||||
void() army_walk6 =[ $prowl_6, army_walk7 ] {ai_walk(3);};
|
||||
void() army_walk7 =[ $prowl_7, army_walk8 ] {ai_walk(4);};
|
||||
void() army_walk8 =[ $prowl_8, army_walk9 ] {ai_walk(4);};
|
||||
void() army_walk9 =[ $prowl_9, army_walk10 ] {ai_walk(2);};
|
||||
void() army_walk10 =[ $prowl_10, army_walk11 ] {ai_walk(2);};
|
||||
void() army_walk11 =[ $prowl_11, army_walk12 ] {ai_walk(2);};
|
||||
void() army_walk12 =[ $prowl_12, army_walk13 ] {ai_walk(1);};
|
||||
void() army_walk13 =[ $prowl_13, army_walk14 ] {ai_walk(0);};
|
||||
void() army_walk14 =[ $prowl_14, army_walk15 ] {ai_walk(1);};
|
||||
void() army_walk15 =[ $prowl_15, army_walk16 ] {ai_walk(1);};
|
||||
void() army_walk16 =[ $prowl_16, army_walk17 ] {ai_walk(1);};
|
||||
void() army_walk17 =[ $prowl_17, army_walk18 ] {ai_walk(3);};
|
||||
void() army_walk18 =[ $prowl_18, army_walk19 ] {ai_walk(3);};
|
||||
void() army_walk19 =[ $prowl_19, army_walk20 ] {ai_walk(3);};
|
||||
void() army_walk20 =[ $prowl_20, army_walk21 ] {ai_walk(3);};
|
||||
void() army_walk21 =[ $prowl_21, army_walk22 ] {ai_walk(2);};
|
||||
void() army_walk22 =[ $prowl_22, army_walk23 ] {ai_walk(1);};
|
||||
void() army_walk23 =[ $prowl_23, army_walk24 ] {ai_walk(1);};
|
||||
void() army_walk24 =[ $prowl_24, army_walk1 ] {ai_walk(1);};
|
||||
|
||||
void() army_run1 =[ $run1, army_run2 ] {
|
||||
if (random() < 0.1)
|
||||
sound (self, CHAN_VOICE, "soldier/idle.wav", 1, ATTN_IDLE);
|
||||
ai_run(11);};
|
||||
void() army_run2 =[ $run2, army_run3 ] {ai_run(15);};
|
||||
void() army_run3 =[ $run3, army_run4 ] {ai_run(10);};
|
||||
void() army_run4 =[ $run4, army_run5 ] {ai_run(10);};
|
||||
void() army_run5 =[ $run5, army_run6 ] {ai_run(8);};
|
||||
void() army_run6 =[ $run6, army_run7 ] {ai_run(15);};
|
||||
void() army_run7 =[ $run7, army_run8 ] {ai_run(10);};
|
||||
void() army_run8 =[ $run8, army_run1 ] {ai_run(8);};
|
||||
|
||||
void() army_fire =
|
||||
{
|
||||
self.effects = self.effects | EF_MUZZLEFLASH;
|
||||
sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);
|
||||
vector dir = self.enemy.origin - self.enemy.velocity * 0.2;
|
||||
dir = normalize (dir - self.origin);
|
||||
FireBullets (4, dir, '0.1 0.1 0');
|
||||
};
|
||||
|
||||
void() army_atk1 =[ $shoot1, army_atk2 ] {ai_face();};
|
||||
void() army_atk2 =[ $shoot2, army_atk3 ] {ai_face();};
|
||||
void() army_atk3 =[ $shoot3, army_atk4 ] {ai_face();};
|
||||
void() army_atk4 =[ $shoot4, army_atk5 ] {ai_face();};
|
||||
void() army_atk5 =[ $shoot5, army_atk6 ] {ai_face();army_fire();};
|
||||
void() army_atk6 =[ $shoot6, army_atk7 ] {ai_face();};
|
||||
void() army_atk7 =[ $shoot7, army_atk8 ] {ai_face();};
|
||||
void() army_atk8 =[ $shoot8, army_atk9 ] {ai_face();};
|
||||
void() army_atk9 =[ $shoot9, army_run1 ] {ai_face();};
|
||||
|
||||
|
||||
void() army_pain1 =[ $pain1, army_pain2 ] {};
|
||||
void() army_pain2 =[ $pain2, army_pain3 ] {};
|
||||
void() army_pain3 =[ $pain3, army_pain4 ] {};
|
||||
void() army_pain4 =[ $pain4, army_pain5 ] {};
|
||||
void() army_pain5 =[ $pain5, army_pain6 ] {};
|
||||
void() army_pain6 =[ $pain6, army_run1 ] {ai_pain(1);};
|
||||
|
||||
void() army_painb1 =[ $painb1, army_painb2 ] {};
|
||||
void() army_painb2 =[ $painb2, army_painb3 ] {ai_painforward(13);};
|
||||
void() army_painb3 =[ $painb3, army_painb4 ] {ai_painforward(9);};
|
||||
void() army_painb4 =[ $painb4, army_painb5 ] {};
|
||||
void() army_painb5 =[ $painb5, army_painb6 ] {};
|
||||
void() army_painb6 =[ $painb6, army_painb7 ] {};
|
||||
void() army_painb7 =[ $painb7, army_painb8 ] {};
|
||||
void() army_painb8 =[ $painb8, army_painb9 ] {};
|
||||
void() army_painb9 =[ $painb9, army_painb10] {};
|
||||
void() army_painb10=[ $painb10, army_painb11] {};
|
||||
void() army_painb11=[ $painb11, army_painb12] {};
|
||||
void() army_painb12=[ $painb12, army_painb13] {ai_pain(2);};
|
||||
void() army_painb13=[ $painb13, army_painb14] {};
|
||||
void() army_painb14=[ $painb14, army_run1 ] {};
|
||||
|
||||
void() army_painc1 =[ $painc1, army_painc2 ] {};
|
||||
void() army_painc2 =[ $painc2, army_painc3 ] {ai_pain(1);};
|
||||
void() army_painc3 =[ $painc3, army_painc4 ] {};
|
||||
void() army_painc4 =[ $painc4, army_painc5 ] {};
|
||||
void() army_painc5 =[ $painc5, army_painc6 ] {ai_painforward(1);};
|
||||
void() army_painc6 =[ $painc6, army_painc7 ] {ai_painforward(1);};
|
||||
void() army_painc7 =[ $painc7, army_painc8 ] {};
|
||||
void() army_painc8 =[ $painc8, army_painc9 ] {ai_pain(1);};
|
||||
void() army_painc9 =[ $painc9, army_painc10] {ai_painforward(4);};
|
||||
void() army_painc10=[ $painc10, army_painc11] {ai_painforward(3);};
|
||||
void() army_painc11=[ $painc11, army_painc12] {ai_painforward(6);};
|
||||
void() army_painc12=[ $painc12, army_painc13] {ai_painforward(8);};
|
||||
void() army_painc13=[ $painc13, army_run1] {};
|
||||
|
||||
void(entity attacker, float damage) army_pain =
|
||||
{
|
||||
if (self.pain_finished > time)
|
||||
return;
|
||||
|
||||
float r = random();
|
||||
if (r < 0.2)
|
||||
{
|
||||
self.pain_finished = time + 0.6;
|
||||
army_pain1 ();
|
||||
sound (self, CHAN_VOICE, "soldier/pain1.wav", 1, ATTN_NORM);
|
||||
}
|
||||
else if (r < 0.6)
|
||||
{
|
||||
self.pain_finished = time + 1.1;
|
||||
army_painb1 ();
|
||||
sound (self, CHAN_VOICE, "soldier/pain2.wav", 1, ATTN_NORM);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.pain_finished = time + 1.1;
|
||||
army_painc1 ();
|
||||
sound (self, CHAN_VOICE, "soldier/pain2.wav", 1, ATTN_NORM);
|
||||
}
|
||||
};
|
||||
|
||||
void() army_die1 =[ $death1, army_die2 ] {};
|
||||
void() army_die2 =[ $death2, army_die3 ] {};
|
||||
void() army_die3 =[ $death3, army_die4 ] {DropBackpack();};
|
||||
void() army_die4 =[ $death4, army_die5 ] {};
|
||||
void() army_die5 =[ $death5, army_die6 ] {};
|
||||
void() army_die6 =[ $death6, army_die7 ] {};
|
||||
void() army_die7 =[ $death7, army_die8 ] {};
|
||||
void() army_die8 =[ $death8, army_die9 ] {};
|
||||
void() army_die9 =[ $death9, army_die10 ] {};
|
||||
void() army_die10 =[ $death10, army_die10 ] {};
|
||||
|
||||
void() army_cdie1 =[ $deathc1, army_cdie2 ] {};
|
||||
void() army_cdie2 =[ $deathc2, army_cdie3 ] {ai_back(5);};
|
||||
void() army_cdie3 =[ $deathc3, army_cdie4 ] {DropBackpack();ai_back(4);};
|
||||
void() army_cdie4 =[ $deathc4, army_cdie5 ] {ai_back(13);};
|
||||
void() army_cdie5 =[ $deathc5, army_cdie6 ] {ai_back(3);};
|
||||
void() army_cdie6 =[ $deathc6, army_cdie7 ] {ai_back(4);};
|
||||
void() army_cdie7 =[ $deathc7, army_cdie8 ] {};
|
||||
void() army_cdie8 =[ $deathc8, army_cdie9 ] {};
|
||||
void() army_cdie9 =[ $deathc9, army_cdie10 ] {};
|
||||
void() army_cdie10 =[ $deathc10, army_cdie11 ] {};
|
||||
void() army_cdie11 =[ $deathc11, army_cdie11 ] {};
|
||||
|
||||
|
||||
void(entity inflictor, entity attacker) army_die =
|
||||
{
|
||||
// check for gib
|
||||
if (self.health < -35)
|
||||
{
|
||||
SpawnGib("progs/gib1.mdl");
|
||||
SpawnGib("progs/gib2.mdl");
|
||||
SpawnGib("progs/gib3.mdl");
|
||||
SpawnGib("progs/gib4.mdl");
|
||||
SpawnGib("progs/gib5.mdl");
|
||||
SpawnGib("progs/blood.mdl");
|
||||
BecomeGibs();
|
||||
return;
|
||||
}
|
||||
|
||||
// regular death
|
||||
sound (self, CHAN_VOICE, "soldier/death1.wav", 1, ATTN_NORM);
|
||||
self.solid = SOLID_NOT;
|
||||
if (random() < 0.5)
|
||||
army_die1 ();
|
||||
else
|
||||
army_cdie1 ();
|
||||
};
|
||||
|
||||
|
||||
/*QUAKED monster_army (1 0 0) (-16 -16 -24) (16 16 40) Ambush
|
||||
{
|
||||
model ("progs/soldier.mdl");
|
||||
}
|
||||
Grunt.
|
||||
*/
|
||||
void() monster_army =
|
||||
{
|
||||
if (deathmatch)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
precache_model ("progs/soldier.mdl");
|
||||
precache_model ("progs/h_guard.mdl");
|
||||
|
||||
precache_sound ("soldier/death1.wav");
|
||||
precache_sound ("soldier/idle.wav");
|
||||
precache_sound ("soldier/pain1.wav");
|
||||
precache_sound ("soldier/pain2.wav");
|
||||
precache_sound ("soldier/sight1.wav");
|
||||
precache_sound ("weapons/guncock.wav");
|
||||
|
||||
self.th_stand = army_stand1;
|
||||
self.th_walk = army_walk1;
|
||||
self.th_run = army_run1;
|
||||
self.th_missile = army_atk1;
|
||||
self.th_pain = army_pain;
|
||||
self.th_die = army_die;
|
||||
|
||||
self.ammo_shells = 5;
|
||||
|
||||
monster_start("progs/soldier.mdl", "progs/h_guard.mdl", 30, 0, '-16 -16 -24', '16 16 40');
|
||||
};
|
||||
221
mod_slipgate/source/server/monsters/tarbaby.qc
Normal file
221
mod_slipgate/source/server/monsters/tarbaby.qc
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
BLOB
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
$cd id1/models/tarbaby
|
||||
$origin 0 0 24
|
||||
$base base
|
||||
|
||||
$skin skin
|
||||
|
||||
$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8 walk9 walk10
|
||||
$frame walk11 walk12 walk13 walk14 walk15 walk16 walk17 walk18 walk19
|
||||
$frame walk20 walk21 walk22 walk23 walk24 walk25
|
||||
|
||||
$frame run1 run2 run3 run4 run5 run6 run7 run8 run9 run10 run11 run12 run13
|
||||
$frame run14 run15 run16 run17 run18 run19 run20 run21 run22 run23
|
||||
$frame run24 run25
|
||||
|
||||
$frame jump1 jump2 jump3 jump4 jump5 jump6
|
||||
|
||||
$frame fly1 fly2 fly3 fly4
|
||||
|
||||
$frame exp
|
||||
|
||||
void() tbaby_stand1 =[ $walk1, tbaby_stand1 ] {ai_stand();};
|
||||
|
||||
void() tbaby_hang1 =[ $walk1, tbaby_hang1 ] {ai_stand();};
|
||||
|
||||
void() tbaby_walk1 =[ $walk1, tbaby_walk2 ] {ai_turn();};
|
||||
void() tbaby_walk2 =[ $walk2, tbaby_walk3 ] {ai_turn();};
|
||||
void() tbaby_walk3 =[ $walk3, tbaby_walk4 ] {ai_turn();};
|
||||
void() tbaby_walk4 =[ $walk4, tbaby_walk5 ] {ai_turn();};
|
||||
void() tbaby_walk5 =[ $walk5, tbaby_walk6 ] {ai_turn();};
|
||||
void() tbaby_walk6 =[ $walk6, tbaby_walk7 ] {ai_turn();};
|
||||
void() tbaby_walk7 =[ $walk7, tbaby_walk8 ] {ai_turn();};
|
||||
void() tbaby_walk8 =[ $walk8, tbaby_walk9 ] {ai_turn();};
|
||||
void() tbaby_walk9 =[ $walk9, tbaby_walk10 ] {ai_turn();};
|
||||
void() tbaby_walk10 =[ $walk10, tbaby_walk11 ] {ai_turn();};
|
||||
void() tbaby_walk11 =[ $walk11, tbaby_walk12 ] {ai_walk(2);};
|
||||
void() tbaby_walk12 =[ $walk12, tbaby_walk13 ] {ai_walk(2);};
|
||||
void() tbaby_walk13 =[ $walk13, tbaby_walk14 ] {ai_walk(2);};
|
||||
void() tbaby_walk14 =[ $walk14, tbaby_walk15 ] {ai_walk(2);};
|
||||
void() tbaby_walk15 =[ $walk15, tbaby_walk16 ] {ai_walk(2);};
|
||||
void() tbaby_walk16 =[ $walk16, tbaby_walk17 ] {ai_walk(2);};
|
||||
void() tbaby_walk17 =[ $walk17, tbaby_walk18 ] {ai_walk(2);};
|
||||
void() tbaby_walk18 =[ $walk18, tbaby_walk19 ] {ai_walk(2);};
|
||||
void() tbaby_walk19 =[ $walk19, tbaby_walk20 ] {ai_walk(2);};
|
||||
void() tbaby_walk20 =[ $walk20, tbaby_walk21 ] {ai_walk(2);};
|
||||
void() tbaby_walk21 =[ $walk21, tbaby_walk22 ] {ai_walk(2);};
|
||||
void() tbaby_walk22 =[ $walk22, tbaby_walk23 ] {ai_walk(2);};
|
||||
void() tbaby_walk23 =[ $walk23, tbaby_walk24 ] {ai_walk(2);};
|
||||
void() tbaby_walk24 =[ $walk24, tbaby_walk25 ] {ai_walk(2);};
|
||||
void() tbaby_walk25 =[ $walk25, tbaby_walk1 ] {ai_walk(2);};
|
||||
|
||||
void() tbaby_run1 =[ $run1, tbaby_run2 ] {ai_face();};
|
||||
void() tbaby_run2 =[ $run2, tbaby_run3 ] {ai_face();};
|
||||
void() tbaby_run3 =[ $run3, tbaby_run4 ] {ai_face();};
|
||||
void() tbaby_run4 =[ $run4, tbaby_run5 ] {ai_face();};
|
||||
void() tbaby_run5 =[ $run5, tbaby_run6 ] {ai_face();};
|
||||
void() tbaby_run6 =[ $run6, tbaby_run7 ] {ai_face();};
|
||||
void() tbaby_run7 =[ $run7, tbaby_run8 ] {ai_face();};
|
||||
void() tbaby_run8 =[ $run8, tbaby_run9 ] {ai_face();};
|
||||
void() tbaby_run9 =[ $run9, tbaby_run10 ] {ai_face();};
|
||||
void() tbaby_run10 =[ $run10, tbaby_run11 ] {ai_face();};
|
||||
void() tbaby_run11 =[ $run11, tbaby_run12 ] {ai_run(2);};
|
||||
void() tbaby_run12 =[ $run12, tbaby_run13 ] {ai_run(2);};
|
||||
void() tbaby_run13 =[ $run13, tbaby_run14 ] {ai_run(2);};
|
||||
void() tbaby_run14 =[ $run14, tbaby_run15 ] {ai_run(2);};
|
||||
void() tbaby_run15 =[ $run15, tbaby_run16 ] {ai_run(2);};
|
||||
void() tbaby_run16 =[ $run16, tbaby_run17 ] {ai_run(2);};
|
||||
void() tbaby_run17 =[ $run17, tbaby_run18 ] {ai_run(2);};
|
||||
void() tbaby_run18 =[ $run18, tbaby_run19 ] {ai_run(2);};
|
||||
void() tbaby_run19 =[ $run19, tbaby_run20 ] {ai_run(2);};
|
||||
void() tbaby_run20 =[ $run20, tbaby_run21 ] {ai_run(2);};
|
||||
void() tbaby_run21 =[ $run21, tbaby_run22 ] {ai_run(2);};
|
||||
void() tbaby_run22 =[ $run22, tbaby_run23 ] {ai_run(2);};
|
||||
void() tbaby_run23 =[ $run23, tbaby_run24 ] {ai_run(2);};
|
||||
void() tbaby_run24 =[ $run24, tbaby_run25 ] {ai_run(2);};
|
||||
void() tbaby_run25 =[ $run25, tbaby_run1 ] {ai_run(2);};
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
||||
void() tbaby_jump1;
|
||||
|
||||
void() Tar_JumpTouch =
|
||||
{
|
||||
local float ldmg;
|
||||
|
||||
if (other.takedamage && other.classname != self.classname)
|
||||
{
|
||||
if ( vlen(self.velocity) > 400 )
|
||||
{
|
||||
ldmg = 10 + 10*random();
|
||||
Damage (other, self, self, ldmg);
|
||||
sound (self, CHAN_WEAPON, "blob/hit1.wav", 1, ATTN_NORM);
|
||||
}
|
||||
}
|
||||
else
|
||||
sound (self, CHAN_WEAPON, "blob/land1.wav", 1, ATTN_NORM);
|
||||
|
||||
|
||||
if (!checkbottom(self))
|
||||
{
|
||||
if (self.flags & FL_ONGROUND)
|
||||
{ // jump randomly to not get hung up
|
||||
//dprint ("popjump\n");
|
||||
self.touch = SUB_Null;
|
||||
self.think = tbaby_run1;
|
||||
self.movetype = MOVETYPE_STEP;
|
||||
self.nextthink = time + 0.1;
|
||||
|
||||
// self.velocity_x = (random() - 0.5) * 600;
|
||||
// self.velocity_y = (random() - 0.5) * 600;
|
||||
// self.velocity_z = 200;
|
||||
// self.flags = self.flags - FL_ONGROUND;
|
||||
}
|
||||
return; // not on ground yet
|
||||
}
|
||||
|
||||
self.touch = SUB_Null;
|
||||
self.think = tbaby_jump1;
|
||||
self.nextthink = time + 0.1;
|
||||
};
|
||||
|
||||
void() tbaby_jump5;
|
||||
|
||||
void() tbaby_fly1 =[ $fly1, tbaby_fly2 ] {};
|
||||
void() tbaby_fly2 =[ $fly2, tbaby_fly3 ] {};
|
||||
void() tbaby_fly3 =[ $fly3, tbaby_fly4 ] {};
|
||||
void() tbaby_fly4 =[ $fly4, tbaby_fly1 ] {
|
||||
self.cnt = self.cnt + 1;
|
||||
if (self.cnt == 4)
|
||||
{
|
||||
//dprint ("spawn hop\n");
|
||||
tbaby_jump5 ();
|
||||
}
|
||||
};
|
||||
|
||||
void() tbaby_jump1 =[ $jump1, tbaby_jump2 ] {ai_face();};
|
||||
void() tbaby_jump2 =[ $jump2, tbaby_jump3 ] {ai_face();};
|
||||
void() tbaby_jump3 =[ $jump3, tbaby_jump4 ] {ai_face();};
|
||||
void() tbaby_jump4 =[ $jump4, tbaby_jump5 ] {ai_face();};
|
||||
void() tbaby_jump5 =[ $jump5, tbaby_jump6 ]
|
||||
{
|
||||
self.movetype = MOVETYPE_BOUNCE;
|
||||
self.touch = Tar_JumpTouch;
|
||||
makevectors (self.angles);
|
||||
self.origin_z = self.origin_z + 1;
|
||||
self.velocity = v_forward * 600 + '0 0 200';
|
||||
self.velocity_z = self.velocity_z + random()*150;
|
||||
if (self.flags & FL_ONGROUND)
|
||||
self.flags = self.flags - FL_ONGROUND;
|
||||
self.cnt = 0;
|
||||
};
|
||||
void() tbaby_jump6 =[ $jump6,tbaby_fly1 ] {};
|
||||
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
void() tbaby_die1 =[ $exp, tbaby_die2 ] {self.takedamage = DAMAGE_NO;};
|
||||
void() tbaby_die2 =[ $exp, tbaby_run1 ]
|
||||
{
|
||||
RadiusDamage (self, self, 120, world);
|
||||
|
||||
sound (self, CHAN_VOICE, "blob/death1.wav", 1, ATTN_NORM);
|
||||
self.origin = self.origin - 8*normalize(self.velocity);
|
||||
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_TAREXPLOSION);
|
||||
WriteCoord (MSG_BROADCAST, self.origin_x);
|
||||
WriteCoord (MSG_BROADCAST, self.origin_y);
|
||||
WriteCoord (MSG_BROADCAST, self.origin_z);
|
||||
|
||||
BecomeExplosion ();
|
||||
};
|
||||
|
||||
void(entity inflictor, entity attacker) tbaby_die =
|
||||
{
|
||||
tbaby_die1();
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/*QUAKED monster_tarbaby (1 0 0) (-16 -16 -24) (16 16 24) Ambush
|
||||
{
|
||||
model ("progs/tarbaby.mdl");
|
||||
}
|
||||
Spawn.
|
||||
*/
|
||||
void() monster_tarbaby =
|
||||
{
|
||||
if (deathmatch)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
precache_model2 ("progs/tarbaby.mdl");
|
||||
|
||||
precache_sound2 ("blob/death1.wav");
|
||||
precache_sound2 ("blob/hit1.wav");
|
||||
precache_sound2 ("blob/land1.wav");
|
||||
precache_sound2 ("blob/sight1.wav");
|
||||
|
||||
self.th_stand = tbaby_stand1;
|
||||
self.th_walk = tbaby_walk1;
|
||||
self.th_run = tbaby_run1;
|
||||
self.th_missile = tbaby_jump1;
|
||||
self.th_melee = tbaby_jump1;
|
||||
self.th_die = tbaby_die;
|
||||
|
||||
monster_start("progs/tarbaby.mdl", "", 80, 0, '-16 -16 -24', '16 16 40');
|
||||
};
|
||||
|
||||
409
mod_slipgate/source/server/monsters/wizard.qc
Normal file
409
mod_slipgate/source/server/monsters/wizard.qc
Normal file
@@ -0,0 +1,409 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
WIZARD
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
$cd id1/models/a_wizard
|
||||
$origin 0 0 24
|
||||
$base wizbase
|
||||
$skin wizbase
|
||||
|
||||
$frame hover1 hover2 hover3 hover4 hover5 hover6 hover7 hover8
|
||||
$frame hover9 hover10 hover11 hover12 hover13 hover14 hover15
|
||||
|
||||
$frame fly1 fly2 fly3 fly4 fly5 fly6 fly7 fly8 fly9 fly10
|
||||
$frame fly11 fly12 fly13 fly14
|
||||
|
||||
$frame magatt1 magatt2 magatt3 magatt4 magatt5 magatt6 magatt7
|
||||
$frame magatt8 magatt9 magatt10 magatt11 magatt12 magatt13
|
||||
|
||||
$frame pain1 pain2 pain3 pain4
|
||||
|
||||
$frame death1 death2 death3 death4 death5 death6 death7 death8
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
WIZARD
|
||||
|
||||
If the player moves behind cover before the missile is launched, launch it
|
||||
at the last visible spot with no velocity leading, in hopes that the player
|
||||
will duck back out and catch it.
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
=============
|
||||
LaunchMissile
|
||||
|
||||
Sets the given entities velocity and angles so that it will hit self.enemy
|
||||
if self.enemy maintains it's current velocity
|
||||
0.1 is moderately accurate, 0.0 is totally accurate
|
||||
=============
|
||||
*/
|
||||
void(entity missile, float mspeed, float accuracy) LaunchMissile =
|
||||
{
|
||||
local vector vec, move;
|
||||
local float fly;
|
||||
|
||||
makevectors (self.angles);
|
||||
|
||||
// set missile speed
|
||||
vec = self.enemy.origin + self.enemy.mins + self.enemy.size * 0.7 - missile.origin;
|
||||
|
||||
// calc aproximate time for missile to reach vec
|
||||
fly = vlen (vec) / mspeed;
|
||||
|
||||
// get the entities xy velocity
|
||||
move = self.enemy.velocity;
|
||||
move_z = 0;
|
||||
|
||||
// project the target forward in time
|
||||
vec = vec + move * fly;
|
||||
|
||||
vec = normalize(vec);
|
||||
vec = vec + accuracy*v_up*(random()- 0.5) + accuracy*v_right*(random()- 0.5);
|
||||
|
||||
missile.velocity = vec * mspeed;
|
||||
|
||||
missile.angles = '0 0 0';
|
||||
missile.angles_y = vectoyaw(missile.velocity);
|
||||
|
||||
// set missile duration
|
||||
missile.nextthink = time + 5;
|
||||
missile.think = SUB_Remove;
|
||||
};
|
||||
|
||||
|
||||
void() wiz_run1;
|
||||
void() wiz_side1;
|
||||
|
||||
/*
|
||||
=================
|
||||
WizardCheckAttack
|
||||
=================
|
||||
*/
|
||||
float() WizardCheckAttack =
|
||||
{
|
||||
local vector spot1, spot2;
|
||||
local entity targ;
|
||||
local float chance;
|
||||
|
||||
if (time < self.attack_finished)
|
||||
return FALSE;
|
||||
if (!enemy_vis)
|
||||
return FALSE;
|
||||
|
||||
if (enemy_range == RANGE_FAR)
|
||||
{
|
||||
if (self.attack_state != AS_STRAIGHT)
|
||||
{
|
||||
self.attack_state = AS_STRAIGHT;
|
||||
wiz_run1 ();
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
targ = self.enemy;
|
||||
|
||||
// see if any entities are in the way of the shot
|
||||
spot1 = self.origin + self.view_ofs;
|
||||
spot2 = targ.origin + targ.view_ofs;
|
||||
|
||||
traceline (spot1, spot2, FALSE, self);
|
||||
|
||||
if (trace_ent != targ)
|
||||
{ // don't have a clear shot, so move to a side
|
||||
if (self.attack_state != AS_STRAIGHT)
|
||||
{
|
||||
self.attack_state = AS_STRAIGHT;
|
||||
wiz_run1 ();
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (enemy_range == RANGE_MELEE)
|
||||
chance = 0.9;
|
||||
else if (enemy_range == RANGE_NEAR)
|
||||
chance = 0.6;
|
||||
else if (enemy_range == RANGE_MID)
|
||||
chance = 0.2;
|
||||
else
|
||||
chance = 0;
|
||||
|
||||
if (random () < chance)
|
||||
{
|
||||
self.attack_state = AS_MISSILE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (enemy_range == RANGE_MID)
|
||||
{
|
||||
if (self.attack_state != AS_STRAIGHT)
|
||||
{
|
||||
self.attack_state = AS_STRAIGHT;
|
||||
wiz_run1 ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self.attack_state != AS_SLIDING)
|
||||
{
|
||||
self.attack_state = AS_SLIDING;
|
||||
wiz_side1 ();
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
/*
|
||||
=================
|
||||
WizardAttackFinished
|
||||
=================
|
||||
*/
|
||||
void() WizardAttackFinished =
|
||||
{
|
||||
if (enemy_range >= RANGE_MID || !enemy_vis)
|
||||
{
|
||||
self.attack_state = AS_STRAIGHT;
|
||||
self.think = wiz_run1;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.attack_state = AS_SLIDING;
|
||||
self.think = wiz_side1;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
FAST ATTACKS
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
void() Wiz_FastFire =
|
||||
{
|
||||
local vector vec;
|
||||
local vector dst;
|
||||
|
||||
if (self.owner.health > 0)
|
||||
{
|
||||
self.owner.effects = self.owner.effects | EF_MUZZLEFLASH;
|
||||
|
||||
makevectors (self.enemy.angles);
|
||||
dst = self.enemy.origin - 13*self.movedir;
|
||||
|
||||
vec = normalize(dst - self.origin);
|
||||
sound (self, CHAN_WEAPON, "wizard/wattack.wav", 1, ATTN_NORM);
|
||||
launch_spike (self.origin, vec);
|
||||
newmis.velocity = vec*600;
|
||||
newmis.owner = self.owner;
|
||||
newmis.classname = "wizspike";
|
||||
setmodel (newmis, "progs/w_spike.mdl");
|
||||
setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
|
||||
}
|
||||
|
||||
remove (self);
|
||||
};
|
||||
|
||||
|
||||
void() Wiz_StartFast =
|
||||
{
|
||||
local entity missile;
|
||||
|
||||
sound (self, CHAN_WEAPON, "wizard/wattack.wav", 1, ATTN_NORM);
|
||||
self.v_angle = self.angles;
|
||||
makevectors (self.angles);
|
||||
|
||||
missile = spawn ();
|
||||
missile.owner = self;
|
||||
missile.nextthink = time + 0.6;
|
||||
setsize (missile, '0 0 0', '0 0 0');
|
||||
setorigin (missile, self.origin + '0 0 30' + v_forward*14 + v_right*14);
|
||||
missile.enemy = self.enemy;
|
||||
missile.nextthink = time + 0.8;
|
||||
missile.think = Wiz_FastFire;
|
||||
missile.movedir = v_right;
|
||||
|
||||
missile = spawn ();
|
||||
missile.owner = self;
|
||||
missile.nextthink = time + 1;
|
||||
setsize (missile, '0 0 0', '0 0 0');
|
||||
setorigin (missile, self.origin + '0 0 30' + v_forward*14 + v_right* -14);
|
||||
missile.enemy = self.enemy;
|
||||
missile.nextthink = time + 0.3;
|
||||
missile.think = Wiz_FastFire;
|
||||
missile.movedir = VEC_ORIGIN - v_right;
|
||||
};
|
||||
|
||||
|
||||
|
||||
void() Wiz_idlesound =
|
||||
{
|
||||
local float wr;
|
||||
wr = random() * 5;
|
||||
|
||||
if (self.wait < time)
|
||||
{
|
||||
self.wait = time + 2;
|
||||
if (wr > 4.5)
|
||||
sound (self, CHAN_VOICE, "wizard/widle1.wav", 1, ATTN_IDLE);
|
||||
if (wr < 1.5)
|
||||
sound (self, CHAN_VOICE, "wizard/widle2.wav", 1, ATTN_IDLE);
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
void() wiz_stand1 =[ $hover1, wiz_stand2 ] {ai_stand();};
|
||||
void() wiz_stand2 =[ $hover2, wiz_stand3 ] {ai_stand();};
|
||||
void() wiz_stand3 =[ $hover3, wiz_stand4 ] {ai_stand();};
|
||||
void() wiz_stand4 =[ $hover4, wiz_stand5 ] {ai_stand();};
|
||||
void() wiz_stand5 =[ $hover5, wiz_stand6 ] {ai_stand();};
|
||||
void() wiz_stand6 =[ $hover6, wiz_stand7 ] {ai_stand();};
|
||||
void() wiz_stand7 =[ $hover7, wiz_stand8 ] {ai_stand();};
|
||||
void() wiz_stand8 =[ $hover8, wiz_stand1 ] {ai_stand();};
|
||||
|
||||
void() wiz_walk1 =[ $hover1, wiz_walk2 ] {ai_walk(8);
|
||||
Wiz_idlesound();};
|
||||
void() wiz_walk2 =[ $hover2, wiz_walk3 ] {ai_walk(8);};
|
||||
void() wiz_walk3 =[ $hover3, wiz_walk4 ] {ai_walk(8);};
|
||||
void() wiz_walk4 =[ $hover4, wiz_walk5 ] {ai_walk(8);};
|
||||
void() wiz_walk5 =[ $hover5, wiz_walk6 ] {ai_walk(8);};
|
||||
void() wiz_walk6 =[ $hover6, wiz_walk7 ] {ai_walk(8);};
|
||||
void() wiz_walk7 =[ $hover7, wiz_walk8 ] {ai_walk(8);};
|
||||
void() wiz_walk8 =[ $hover8, wiz_walk1 ] {ai_walk(8);};
|
||||
|
||||
void() wiz_side1 =[ $hover1, wiz_side2 ] {ai_run(8);
|
||||
Wiz_idlesound();};
|
||||
void() wiz_side2 =[ $hover2, wiz_side3 ] {ai_run(8);};
|
||||
void() wiz_side3 =[ $hover3, wiz_side4 ] {ai_run(8);};
|
||||
void() wiz_side4 =[ $hover4, wiz_side5 ] {ai_run(8);};
|
||||
void() wiz_side5 =[ $hover5, wiz_side6 ] {ai_run(8);};
|
||||
void() wiz_side6 =[ $hover6, wiz_side7 ] {ai_run(8);};
|
||||
void() wiz_side7 =[ $hover7, wiz_side8 ] {ai_run(8);};
|
||||
void() wiz_side8 =[ $hover8, wiz_side1 ] {ai_run(8);};
|
||||
|
||||
void() wiz_run1 =[ $fly1, wiz_run2 ] {ai_run(16);
|
||||
Wiz_idlesound();
|
||||
};
|
||||
void() wiz_run2 =[ $fly2, wiz_run3 ] {ai_run(16);};
|
||||
void() wiz_run3 =[ $fly3, wiz_run4 ] {ai_run(16);};
|
||||
void() wiz_run4 =[ $fly4, wiz_run5 ] {ai_run(16);};
|
||||
void() wiz_run5 =[ $fly5, wiz_run6 ] {ai_run(16);};
|
||||
void() wiz_run6 =[ $fly6, wiz_run7 ] {ai_run(16);};
|
||||
void() wiz_run7 =[ $fly7, wiz_run8 ] {ai_run(16);};
|
||||
void() wiz_run8 =[ $fly8, wiz_run9 ] {ai_run(16);};
|
||||
void() wiz_run9 =[ $fly9, wiz_run10 ] {ai_run(16);};
|
||||
void() wiz_run10 =[ $fly10, wiz_run11 ] {ai_run(16);};
|
||||
void() wiz_run11 =[ $fly11, wiz_run12 ] {ai_run(16);};
|
||||
void() wiz_run12 =[ $fly12, wiz_run13 ] {ai_run(16);};
|
||||
void() wiz_run13 =[ $fly13, wiz_run14 ] {ai_run(16);};
|
||||
void() wiz_run14 =[ $fly14, wiz_run1 ] {ai_run(16);};
|
||||
|
||||
void() wiz_fast1 =[ $magatt1, wiz_fast2 ] {ai_face();Wiz_StartFast();};
|
||||
void() wiz_fast2 =[ $magatt2, wiz_fast3 ] {ai_face();};
|
||||
void() wiz_fast3 =[ $magatt3, wiz_fast4 ] {ai_face();};
|
||||
void() wiz_fast4 =[ $magatt4, wiz_fast5 ] {ai_face();};
|
||||
void() wiz_fast5 =[ $magatt5, wiz_fast6 ] {ai_face();};
|
||||
void() wiz_fast6 =[ $magatt6, wiz_fast7 ] {ai_face();};
|
||||
void() wiz_fast7 =[ $magatt5, wiz_fast8 ] {ai_face();};
|
||||
void() wiz_fast8 =[ $magatt4, wiz_fast9 ] {ai_face();};
|
||||
void() wiz_fast9 =[ $magatt3, wiz_fast10 ] {ai_face();};
|
||||
void() wiz_fast10 =[ $magatt2, wiz_run1 ] {ai_face();SUB_AttackFinished(2);WizardAttackFinished ();};
|
||||
|
||||
void() wiz_pain1 =[ $pain1, wiz_pain2 ] {};
|
||||
void() wiz_pain2 =[ $pain2, wiz_pain3 ] {};
|
||||
void() wiz_pain3 =[ $pain3, wiz_pain4 ] {};
|
||||
void() wiz_pain4 =[ $pain4, wiz_run1 ] {};
|
||||
|
||||
void() wiz_death1 =[ $death1, wiz_death2 ] {};
|
||||
void() wiz_death2 =[ $death2, wiz_death3 ] {};
|
||||
void() wiz_death3 =[ $death3, wiz_death4 ] {};
|
||||
void() wiz_death4 =[ $death4, wiz_death5 ] {};
|
||||
void() wiz_death5 =[ $death5, wiz_death6 ] {};
|
||||
void() wiz_death6 =[ $death6, wiz_death7 ] {};
|
||||
void() wiz_death7 =[ $death7, wiz_death8 ] {};
|
||||
void() wiz_death8 =[ $death8, wiz_death8 ] {};
|
||||
|
||||
void(entity inflictor, entity attacker) wiz_die =
|
||||
{
|
||||
// check for gib
|
||||
if (self.health < -40)
|
||||
{
|
||||
SpawnGib("progs/gib3.mdl");
|
||||
SpawnGib("progs/gib4.mdl");
|
||||
SpawnGib("progs/gib5.mdl");
|
||||
SpawnGib("progs/blood.mdl");
|
||||
SpawnGib("progs/blood.mdl");
|
||||
BecomeGibs();
|
||||
return;
|
||||
}
|
||||
|
||||
sound (self, CHAN_VOICE, "wizard/wdeath.wav", 1, ATTN_NORM);
|
||||
self.solid = SOLID_NOT;
|
||||
|
||||
self.velocity_x = crandom() * 200;
|
||||
self.velocity_y = crandom() * 200;
|
||||
self.velocity_z = 100 + 100 * random();
|
||||
self.flags = self.flags - (self.flags & FL_ONGROUND);
|
||||
|
||||
wiz_death1 ();
|
||||
};
|
||||
|
||||
|
||||
void(entity attacker, float damage) Wiz_Pain =
|
||||
{
|
||||
if (random()*70 > damage)
|
||||
return;
|
||||
if (self.pain_finished > time)
|
||||
return;
|
||||
sound (self, CHAN_VOICE, "wizard/wpain.wav", 1, ATTN_NORM);
|
||||
self.pain_finished = time + 0.4;
|
||||
wiz_pain1 ();
|
||||
};
|
||||
|
||||
void() Wiz_Missile =
|
||||
{
|
||||
wiz_fast1();
|
||||
};
|
||||
|
||||
/*QUAKED monster_wizard (1 0 0) (-16 -16 -24) (16 16 40) Ambush
|
||||
{
|
||||
model ("progs/wizard.mdl");
|
||||
}
|
||||
Scrag.
|
||||
*/
|
||||
void() monster_wizard =
|
||||
{
|
||||
if (deathmatch)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
precache_model ("progs/wizard.mdl");
|
||||
precache_model ("progs/h_wizard.mdl");
|
||||
precache_model ("progs/w_spike.mdl");
|
||||
|
||||
precache_sound ("wizard/hit.wav");
|
||||
precache_sound ("wizard/wattack.wav");
|
||||
precache_sound ("wizard/wdeath.wav");
|
||||
precache_sound ("wizard/widle1.wav");
|
||||
precache_sound ("wizard/widle2.wav");
|
||||
precache_sound ("wizard/wpain.wav");
|
||||
precache_sound ("wizard/wsight.wav");
|
||||
|
||||
self.th_stand = wiz_stand1;
|
||||
self.th_walk = wiz_walk1;
|
||||
self.th_run = wiz_run1;
|
||||
self.th_missile = Wiz_Missile;
|
||||
self.th_pain = Wiz_Pain;
|
||||
self.th_die = wiz_die;
|
||||
|
||||
monster_start("progs/wizard.mdl", "progs/h_wizard.mdl", 80, FL_FLY, '-16 -16 -24', '16 16 40');
|
||||
};
|
||||
508
mod_slipgate/source/server/monsters/zombie.qc
Normal file
508
mod_slipgate/source/server/monsters/zombie.qc
Normal file
@@ -0,0 +1,508 @@
|
||||
static enumflags { ZOMBIE_CRUCIFIED, ZOMBIE_AMBUSH };
|
||||
|
||||
$frame stand1 stand2 stand3 stand4 stand5 stand6 stand7 stand8
|
||||
$frame stand9 stand10 stand11 stand12 stand13 stand14 stand15
|
||||
|
||||
$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8 walk9 walk10 walk11
|
||||
$frame walk12 walk13 walk14 walk15 walk16 walk17 walk18 walk19
|
||||
|
||||
$frame run1 run2 run3 run4 run5 run6 run7 run8 run9 run10 run11 run12
|
||||
$frame run13 run14 run15 run16 run17 run18
|
||||
|
||||
$frame atta1 atta2 atta3 atta4 atta5 atta6 atta7 atta8 atta9 atta10 atta11
|
||||
$frame atta12 atta13
|
||||
|
||||
$frame attb1 attb2 attb3 attb4 attb5 attb6 attb7 attb8 attb9 attb10 attb11
|
||||
$frame attb12 attb13 attb14
|
||||
|
||||
$frame attc1 attc2 attc3 attc4 attc5 attc6 attc7 attc8 attc9 attc10 attc11
|
||||
$frame attc12
|
||||
|
||||
$frame paina1 paina2 paina3 paina4 paina5 paina6 paina7 paina8 paina9 paina10
|
||||
$frame paina11 paina12
|
||||
|
||||
$frame painb1 painb2 painb3 painb4 painb5 painb6 painb7 painb8 painb9 painb10
|
||||
$frame painb11 painb12 painb13 painb14 painb15 painb16 painb17 painb18 painb19
|
||||
$frame painb20 painb21 painb22 painb23 painb24 painb25 painb26 painb27 painb28
|
||||
|
||||
$frame painc1 painc2 painc3 painc4 painc5 painc6 painc7 painc8 painc9 painc10
|
||||
$frame painc11 painc12 painc13 painc14 painc15 painc16 painc17 painc18
|
||||
|
||||
$frame paind1 paind2 paind3 paind4 paind5 paind6 paind7 paind8 paind9 paind10
|
||||
$frame paind11 paind12 paind13
|
||||
|
||||
$frame paine1 paine2 paine3 paine4 paine5 paine6 paine7 paine8 paine9 paine10
|
||||
$frame paine11 paine12 paine13 paine14 paine15 paine16 paine17 paine18 paine19
|
||||
$frame paine20 paine21 paine22 paine23 paine24 paine25 paine26 paine27 paine28
|
||||
$frame paine29 paine30
|
||||
|
||||
$frame cruc_1 cruc_2 cruc_3 cruc_4 cruc_5 cruc_6
|
||||
|
||||
//=============================================================================
|
||||
|
||||
.float inpain;
|
||||
|
||||
void() zombie_idle_sound =
|
||||
{
|
||||
if (random() > 0.2)
|
||||
return;
|
||||
|
||||
float r = randomrange(3);
|
||||
if (r == 0)
|
||||
sound (self, CHAN_VOICE, "zombie/idle_w2.wav", 1, ATTN_IDLE);
|
||||
else if (r == 1)
|
||||
sound (self, CHAN_VOICE, "zombie/z_idle.wav", 1, ATTN_IDLE);
|
||||
else
|
||||
sound (self, CHAN_VOICE, "zombie/z_idle1.wav", 1, ATTN_IDLE);
|
||||
};
|
||||
|
||||
void() zombie_stand1 =[ $stand1, zombie_stand2 ] {ai_stand();};
|
||||
void() zombie_stand2 =[ $stand2, zombie_stand3 ] {ai_stand();};
|
||||
void() zombie_stand3 =[ $stand3, zombie_stand4 ] {ai_stand();};
|
||||
void() zombie_stand4 =[ $stand4, zombie_stand5 ] {ai_stand();};
|
||||
void() zombie_stand5 =[ $stand5, zombie_stand6 ] {ai_stand();};
|
||||
void() zombie_stand6 =[ $stand6, zombie_stand7 ] {ai_stand();};
|
||||
void() zombie_stand7 =[ $stand7, zombie_stand8 ] {ai_stand();};
|
||||
void() zombie_stand8 =[ $stand8, zombie_stand9 ] {ai_stand();};
|
||||
void() zombie_stand9 =[ $stand9, zombie_stand10 ] {ai_stand();};
|
||||
void() zombie_stand10 =[ $stand10, zombie_stand11 ] {ai_stand();};
|
||||
void() zombie_stand11 =[ $stand11, zombie_stand12 ] {ai_stand();};
|
||||
void() zombie_stand12 =[ $stand12, zombie_stand13 ] {ai_stand();};
|
||||
void() zombie_stand13 =[ $stand13, zombie_stand14 ] {ai_stand();};
|
||||
void() zombie_stand14 =[ $stand14, zombie_stand15 ] {ai_stand();};
|
||||
void() zombie_stand15 =[ $stand15, zombie_stand1 ] {ai_stand();};
|
||||
|
||||
void() zombie_cruc1 = [ $cruc_1, zombie_cruc2 ] {zombie_idle_sound();self.nextthink = time + 0.1 + random()*0.1;};
|
||||
void() zombie_cruc2 = [ $cruc_2, zombie_cruc3 ] {self.nextthink = time + 0.1 + random()*0.1;};
|
||||
void() zombie_cruc3 = [ $cruc_3, zombie_cruc4 ] {self.nextthink = time + 0.1 + random()*0.1;};
|
||||
void() zombie_cruc4 = [ $cruc_4, zombie_cruc5 ] {self.nextthink = time + 0.1 + random()*0.1;};
|
||||
void() zombie_cruc5 = [ $cruc_5, zombie_cruc6 ] {self.nextthink = time + 0.1 + random()*0.1;};
|
||||
void() zombie_cruc6 = [ $cruc_6, zombie_cruc1 ] {self.nextthink = time + 0.1 + random()*0.1;};
|
||||
|
||||
void() zombie_walk1 =[ $walk1, zombie_walk2 ] {ai_walk(0);};
|
||||
void() zombie_walk2 =[ $walk2, zombie_walk3 ] {ai_walk(2);};
|
||||
void() zombie_walk3 =[ $walk3, zombie_walk4 ] {ai_walk(3);};
|
||||
void() zombie_walk4 =[ $walk4, zombie_walk5 ] {ai_walk(2);};
|
||||
void() zombie_walk5 =[ $walk5, zombie_walk6 ] {ai_walk(1);};
|
||||
void() zombie_walk6 =[ $walk6, zombie_walk7 ] {ai_walk(0);};
|
||||
void() zombie_walk7 =[ $walk7, zombie_walk8 ] {ai_walk(0);};
|
||||
void() zombie_walk8 =[ $walk8, zombie_walk9 ] {ai_walk(0);};
|
||||
void() zombie_walk9 =[ $walk9, zombie_walk10 ] {ai_walk(0);};
|
||||
void() zombie_walk10 =[ $walk10, zombie_walk11 ] {ai_walk(0);};
|
||||
void() zombie_walk11 =[ $walk11, zombie_walk12 ] {ai_walk(2);};
|
||||
void() zombie_walk12 =[ $walk12, zombie_walk13 ] {ai_walk(2);};
|
||||
void() zombie_walk13 =[ $walk13, zombie_walk14 ] {ai_walk(1);};
|
||||
void() zombie_walk14 =[ $walk14, zombie_walk15 ] {ai_walk(0);};
|
||||
void() zombie_walk15 =[ $walk15, zombie_walk16 ] {ai_walk(0);};
|
||||
void() zombie_walk16 =[ $walk16, zombie_walk17 ] {ai_walk(0);};
|
||||
void() zombie_walk17 =[ $walk17, zombie_walk18 ] {ai_walk(0);};
|
||||
void() zombie_walk18 =[ $walk18, zombie_walk19 ] {ai_walk(0);};
|
||||
void() zombie_walk19 =[ $walk19, zombie_walk1 ] {ai_walk(0);zombie_idle_sound();};
|
||||
|
||||
void() zombie_run1 =[ $run1, zombie_run2 ] {ai_run(1);self.inpain = 0;};
|
||||
void() zombie_run2 =[ $run2, zombie_run3 ] {ai_run(1);};
|
||||
void() zombie_run3 =[ $run3, zombie_run4 ] {ai_run(0);};
|
||||
void() zombie_run4 =[ $run4, zombie_run5 ] {ai_run(1);};
|
||||
void() zombie_run5 =[ $run5, zombie_run6 ] {ai_run(2);};
|
||||
void() zombie_run6 =[ $run6, zombie_run7 ] {ai_run(3);};
|
||||
void() zombie_run7 =[ $run7, zombie_run8 ] {ai_run(4);};
|
||||
void() zombie_run8 =[ $run8, zombie_run9 ] {ai_run(4);};
|
||||
void() zombie_run9 =[ $run9, zombie_run10 ] {ai_run(2);};
|
||||
void() zombie_run10 =[ $run10, zombie_run11 ] {ai_run(0);};
|
||||
void() zombie_run11 =[ $run11, zombie_run12 ] {ai_run(0);};
|
||||
void() zombie_run12 =[ $run12, zombie_run13 ] {ai_run(0);};
|
||||
void() zombie_run13 =[ $run13, zombie_run14 ] {ai_run(2);};
|
||||
void() zombie_run14 =[ $run14, zombie_run15 ] {ai_run(4);};
|
||||
void() zombie_run15 =[ $run15, zombie_run16 ] {ai_run(6);};
|
||||
void() zombie_run16 =[ $run16, zombie_run17 ] {ai_run(7);};
|
||||
void() zombie_run17 =[ $run17, zombie_run18 ] {ai_run(3);};
|
||||
void() zombie_run18 =[ $run18, zombie_run1 ] {ai_run(8);zombie_idle_sound();};
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
ATTACKS
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
void() ZombieGrenadeTouch =
|
||||
{
|
||||
SpawnTouchblood(32);
|
||||
|
||||
if (other.takedamage)
|
||||
{
|
||||
Damage (other, self, self.owner, 10);
|
||||
sound (self, CHAN_WEAPON, "zombie/z_hit.wav", 1, ATTN_NORM);
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
|
||||
sound (self, CHAN_WEAPON, "zombie/z_miss.wav", 1, ATTN_NORM);
|
||||
|
||||
self.touch = SUB_Null;
|
||||
self.velocity = '0 0 0';
|
||||
|
||||
self.think = SUB_Fade;
|
||||
self.nextthink = time + 2 + random()*2;
|
||||
};
|
||||
|
||||
/*
|
||||
================
|
||||
ZombieFireGrenade
|
||||
================
|
||||
*/
|
||||
void(vector st) ZombieFireGrenade =
|
||||
{
|
||||
local entity missile;
|
||||
local vector org;
|
||||
|
||||
sound (self, CHAN_WEAPON, "zombie/z_shot1.wav", 1, ATTN_NORM);
|
||||
|
||||
missile = spawn ();
|
||||
missile.owner = self;
|
||||
missile.movetype = MOVETYPE_TOSS;
|
||||
missile.solid = SOLID_BBOX;
|
||||
|
||||
// calc org
|
||||
org = self.origin + st_x * v_forward + st_y * v_right + (st_z - 24) * v_up;
|
||||
|
||||
// set missile speed
|
||||
|
||||
makevectors (self.angles);
|
||||
|
||||
missile.velocity = normalize(self.enemy.origin - org);
|
||||
missile.velocity = missile.velocity * 600;
|
||||
missile.velocity_z = 200;
|
||||
|
||||
missile.avelocity = '3000 1000 2000';
|
||||
|
||||
missile.touch = ZombieGrenadeTouch;
|
||||
|
||||
// set missile duration
|
||||
missile.nextthink = time + 2.5;
|
||||
missile.think = SUB_Remove;
|
||||
|
||||
setmodel (missile, "progs/zom_gib.mdl");
|
||||
setsize (missile, '0 0 0', '0 0 0');
|
||||
setorigin (missile, org);
|
||||
};
|
||||
|
||||
|
||||
void() zombie_atta1 =[ $atta1, zombie_atta2 ] {ai_face();};
|
||||
void() zombie_atta2 =[ $atta2, zombie_atta3 ] {ai_face();};
|
||||
void() zombie_atta3 =[ $atta3, zombie_atta4 ] {ai_face();};
|
||||
void() zombie_atta4 =[ $atta4, zombie_atta5 ] {ai_face();};
|
||||
void() zombie_atta5 =[ $atta5, zombie_atta6 ] {ai_face();};
|
||||
void() zombie_atta6 =[ $atta6, zombie_atta7 ] {ai_face();};
|
||||
void() zombie_atta7 =[ $atta7, zombie_atta8 ] {ai_face();};
|
||||
void() zombie_atta8 =[ $atta8, zombie_atta9 ] {ai_face();};
|
||||
void() zombie_atta9 =[ $atta9, zombie_atta10 ] {ai_face();};
|
||||
void() zombie_atta10 =[ $atta10, zombie_atta11 ] {ai_face();};
|
||||
void() zombie_atta11 =[ $atta11, zombie_atta12 ] {ai_face();};
|
||||
void() zombie_atta12 =[ $atta12, zombie_atta13 ] {ai_face();};
|
||||
void() zombie_atta13 =[ $atta13, zombie_run1 ] {ai_face();ZombieFireGrenade('-10 -22 30');};
|
||||
|
||||
void() zombie_attb1 =[ $attb1, zombie_attb2 ] {ai_face();};
|
||||
void() zombie_attb2 =[ $attb2, zombie_attb3 ] {ai_face();};
|
||||
void() zombie_attb3 =[ $attb3, zombie_attb4 ] {ai_face();};
|
||||
void() zombie_attb4 =[ $attb4, zombie_attb5 ] {ai_face();};
|
||||
void() zombie_attb5 =[ $attb5, zombie_attb6 ] {ai_face();};
|
||||
void() zombie_attb6 =[ $attb6, zombie_attb7 ] {ai_face();};
|
||||
void() zombie_attb7 =[ $attb7, zombie_attb8 ] {ai_face();};
|
||||
void() zombie_attb8 =[ $attb8, zombie_attb9 ] {ai_face();};
|
||||
void() zombie_attb9 =[ $attb9, zombie_attb10 ] {ai_face();};
|
||||
void() zombie_attb10 =[ $attb10, zombie_attb11 ] {ai_face();};
|
||||
void() zombie_attb11 =[ $attb11, zombie_attb12 ] {ai_face();};
|
||||
void() zombie_attb12 =[ $attb12, zombie_attb13 ] {ai_face();};
|
||||
void() zombie_attb13 =[ $attb13, zombie_attb14 ] {ai_face();};
|
||||
void() zombie_attb14 =[ $attb13, zombie_run1 ] {ai_face();ZombieFireGrenade('-10 -24 29');};
|
||||
|
||||
void() zombie_attc1 =[ $attc1, zombie_attc2 ] {ai_face();};
|
||||
void() zombie_attc2 =[ $attc2, zombie_attc3 ] {ai_face();};
|
||||
void() zombie_attc3 =[ $attc3, zombie_attc4 ] {ai_face();};
|
||||
void() zombie_attc4 =[ $attc4, zombie_attc5 ] {ai_face();};
|
||||
void() zombie_attc5 =[ $attc5, zombie_attc6 ] {ai_face();};
|
||||
void() zombie_attc6 =[ $attc6, zombie_attc7 ] {ai_face();};
|
||||
void() zombie_attc7 =[ $attc7, zombie_attc8 ] {ai_face();};
|
||||
void() zombie_attc8 =[ $attc8, zombie_attc9 ] {ai_face();};
|
||||
void() zombie_attc9 =[ $attc9, zombie_attc10 ] {ai_face();};
|
||||
void() zombie_attc10 =[ $attc10, zombie_attc11 ] {ai_face();};
|
||||
void() zombie_attc11 =[ $attc11, zombie_attc12 ] {ai_face();};
|
||||
void() zombie_attc12 =[ $attc12, zombie_run1 ] {ai_face();ZombieFireGrenade('-12 -19 29');};
|
||||
|
||||
void() zombie_missile =
|
||||
{
|
||||
local float r;
|
||||
|
||||
r = random();
|
||||
|
||||
if (r < 0.3)
|
||||
zombie_atta1 ();
|
||||
else if (r < 0.6)
|
||||
zombie_attb1 ();
|
||||
else
|
||||
zombie_attc1 ();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
PAIN
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
void() zombie_paina1 =[ $paina1, zombie_paina2 ] {sound (self, CHAN_VOICE, "zombie/z_pain.wav", 1, ATTN_NORM);};
|
||||
void() zombie_paina2 =[ $paina2, zombie_paina3 ] {ai_painforward(3);};
|
||||
void() zombie_paina3 =[ $paina3, zombie_paina4 ] {ai_painforward(1);};
|
||||
void() zombie_paina4 =[ $paina4, zombie_paina5 ] {ai_pain(1);};
|
||||
void() zombie_paina5 =[ $paina5, zombie_paina6 ] {ai_pain(3);};
|
||||
void() zombie_paina6 =[ $paina6, zombie_paina7 ] {ai_pain(1);};
|
||||
void() zombie_paina7 =[ $paina7, zombie_paina8 ] {};
|
||||
void() zombie_paina8 =[ $paina8, zombie_paina9 ] {};
|
||||
void() zombie_paina9 =[ $paina9, zombie_paina10 ] {};
|
||||
void() zombie_paina10 =[ $paina10, zombie_paina11 ] {};
|
||||
void() zombie_paina11 =[ $paina11, zombie_paina12 ] {};
|
||||
void() zombie_paina12 =[ $paina12, zombie_run1 ] {};
|
||||
|
||||
void() zombie_painb1 =[ $painb1, zombie_painb2 ] {sound (self, CHAN_VOICE, "zombie/z_pain1.wav", 1, ATTN_NORM);};
|
||||
void() zombie_painb2 =[ $painb2, zombie_painb3 ] {ai_pain(2);};
|
||||
void() zombie_painb3 =[ $painb3, zombie_painb4 ] {ai_pain(8);};
|
||||
void() zombie_painb4 =[ $painb4, zombie_painb5 ] {ai_pain(6);};
|
||||
void() zombie_painb5 =[ $painb5, zombie_painb6 ] {ai_pain(2);};
|
||||
void() zombie_painb6 =[ $painb6, zombie_painb7 ] {};
|
||||
void() zombie_painb7 =[ $painb7, zombie_painb8 ] {};
|
||||
void() zombie_painb8 =[ $painb8, zombie_painb9 ] {};
|
||||
void() zombie_painb9 =[ $painb9, zombie_painb10 ] {sound (self, CHAN_BODY, "zombie/z_fall.wav", 1, ATTN_NORM);};
|
||||
void() zombie_painb10 =[ $painb10, zombie_painb11 ] {};
|
||||
void() zombie_painb11 =[ $painb11, zombie_painb12 ] {};
|
||||
void() zombie_painb12 =[ $painb12, zombie_painb13 ] {};
|
||||
void() zombie_painb13 =[ $painb13, zombie_painb14 ] {};
|
||||
void() zombie_painb14 =[ $painb14, zombie_painb15 ] {};
|
||||
void() zombie_painb15 =[ $painb15, zombie_painb16 ] {};
|
||||
void() zombie_painb16 =[ $painb16, zombie_painb17 ] {};
|
||||
void() zombie_painb17 =[ $painb17, zombie_painb18 ] {};
|
||||
void() zombie_painb18 =[ $painb18, zombie_painb19 ] {};
|
||||
void() zombie_painb19 =[ $painb19, zombie_painb20 ] {};
|
||||
void() zombie_painb20 =[ $painb20, zombie_painb21 ] {};
|
||||
void() zombie_painb21 =[ $painb21, zombie_painb22 ] {};
|
||||
void() zombie_painb22 =[ $painb22, zombie_painb23 ] {};
|
||||
void() zombie_painb23 =[ $painb23, zombie_painb24 ] {};
|
||||
void() zombie_painb24 =[ $painb24, zombie_painb25 ] {};
|
||||
void() zombie_painb25 =[ $painb25, zombie_painb26 ] {ai_painforward(1);};
|
||||
void() zombie_painb26 =[ $painb26, zombie_painb27 ] {};
|
||||
void() zombie_painb27 =[ $painb27, zombie_painb28 ] {};
|
||||
void() zombie_painb28 =[ $painb28, zombie_run1 ] {};
|
||||
|
||||
void() zombie_painc1 =[ $painc1, zombie_painc2 ] {sound (self, CHAN_VOICE, "zombie/z_pain1.wav", 1, ATTN_NORM);};
|
||||
void() zombie_painc2 =[ $painc2, zombie_painc3 ] {};
|
||||
void() zombie_painc3 =[ $painc3, zombie_painc4 ] {ai_pain(3);};
|
||||
void() zombie_painc4 =[ $painc4, zombie_painc5 ] {ai_pain(1);};
|
||||
void() zombie_painc5 =[ $painc5, zombie_painc6 ] {};
|
||||
void() zombie_painc6 =[ $painc6, zombie_painc7 ] {};
|
||||
void() zombie_painc7 =[ $painc7, zombie_painc8 ] {};
|
||||
void() zombie_painc8 =[ $painc8, zombie_painc9 ] {};
|
||||
void() zombie_painc9 =[ $painc9, zombie_painc10 ] {};
|
||||
void() zombie_painc10 =[ $painc10, zombie_painc11 ] {};
|
||||
void() zombie_painc11 =[ $painc11, zombie_painc12 ] {ai_painforward(1);};
|
||||
void() zombie_painc12 =[ $painc12, zombie_painc13 ] {ai_painforward(1);};
|
||||
void() zombie_painc13 =[ $painc13, zombie_painc14 ] {};
|
||||
void() zombie_painc14 =[ $painc14, zombie_painc15 ] {};
|
||||
void() zombie_painc15 =[ $painc15, zombie_painc16 ] {};
|
||||
void() zombie_painc16 =[ $painc16, zombie_painc17 ] {};
|
||||
void() zombie_painc17 =[ $painc17, zombie_painc18 ] {};
|
||||
void() zombie_painc18 =[ $painc18, zombie_run1 ] {};
|
||||
|
||||
void() zombie_paind1 =[ $paind1, zombie_paind2 ] {sound (self, CHAN_VOICE, "zombie/z_pain.wav", 1, ATTN_NORM);};
|
||||
void() zombie_paind2 =[ $paind2, zombie_paind3 ] {};
|
||||
void() zombie_paind3 =[ $paind3, zombie_paind4 ] {};
|
||||
void() zombie_paind4 =[ $paind4, zombie_paind5 ] {};
|
||||
void() zombie_paind5 =[ $paind5, zombie_paind6 ] {};
|
||||
void() zombie_paind6 =[ $paind6, zombie_paind7 ] {};
|
||||
void() zombie_paind7 =[ $paind7, zombie_paind8 ] {};
|
||||
void() zombie_paind8 =[ $paind8, zombie_paind9 ] {};
|
||||
void() zombie_paind9 =[ $paind9, zombie_paind10 ] {ai_pain(1);};
|
||||
void() zombie_paind10 =[ $paind10, zombie_paind11 ] {};
|
||||
void() zombie_paind11 =[ $paind11, zombie_paind12 ] {};
|
||||
void() zombie_paind12 =[ $paind12, zombie_paind13 ] {};
|
||||
void() zombie_paind13 =[ $paind13, zombie_run1 ] {};
|
||||
|
||||
void() zombie_paine1 =[ $paine1, zombie_paine2 ] {sound (self, CHAN_VOICE, "zombie/z_pain.wav", 1, ATTN_NORM);self.health = 60;};
|
||||
void() zombie_paine2 =[ $paine2, zombie_paine3 ] {ai_pain(8);};
|
||||
void() zombie_paine3 =[ $paine3, zombie_paine4 ] {ai_pain(5);};
|
||||
void() zombie_paine4 =[ $paine4, zombie_paine5 ] {ai_pain(3);};
|
||||
void() zombie_paine5 =[ $paine5, zombie_paine6 ] {ai_pain(1);};
|
||||
void() zombie_paine6 =[ $paine6, zombie_paine7 ] {ai_pain(2);};
|
||||
void() zombie_paine7 =[ $paine7, zombie_paine8 ] {ai_pain(1);};
|
||||
void() zombie_paine8 =[ $paine8, zombie_paine9 ] {ai_pain(1);};
|
||||
void() zombie_paine9 =[ $paine9, zombie_paine10 ] {ai_pain(2);};
|
||||
void() zombie_paine10 =[ $paine10, zombie_paine11 ] {
|
||||
sound (self, CHAN_BODY, "zombie/z_fall.wav", 1, ATTN_NORM);
|
||||
self.solid = SOLID_NOT;
|
||||
};
|
||||
void() zombie_paine11 =[ $paine11, zombie_paine12 ] {self.nextthink = self.nextthink + 5;self.health = 60;};
|
||||
void() zombie_paine12 =[ $paine12, zombie_paine13 ]{
|
||||
// see if ok to stand up
|
||||
self.health = 60;
|
||||
sound (self, CHAN_VOICE, "zombie/z_idle.wav", 1, ATTN_IDLE);
|
||||
self.solid = SOLID_SLIDEBOX;
|
||||
if (!walkmove (0, 0))
|
||||
{
|
||||
self.think = zombie_paine11;
|
||||
self.solid = SOLID_NOT;
|
||||
return;
|
||||
}
|
||||
};
|
||||
void() zombie_paine13 =[ $paine13, zombie_paine14 ] {};
|
||||
void() zombie_paine14 =[ $paine14, zombie_paine15 ] {};
|
||||
void() zombie_paine15 =[ $paine15, zombie_paine16 ] {};
|
||||
void() zombie_paine16 =[ $paine16, zombie_paine17 ] {};
|
||||
void() zombie_paine17 =[ $paine17, zombie_paine18 ] {};
|
||||
void() zombie_paine18 =[ $paine18, zombie_paine19 ] {};
|
||||
void() zombie_paine19 =[ $paine19, zombie_paine20 ] {};
|
||||
void() zombie_paine20 =[ $paine20, zombie_paine21 ] {};
|
||||
void() zombie_paine21 =[ $paine21, zombie_paine22 ] {};
|
||||
void() zombie_paine22 =[ $paine22, zombie_paine23 ] {};
|
||||
void() zombie_paine23 =[ $paine23, zombie_paine24 ] {};
|
||||
void() zombie_paine24 =[ $paine24, zombie_paine25 ] {};
|
||||
void() zombie_paine25 =[ $paine25, zombie_paine26 ] {ai_painforward(5);};
|
||||
void() zombie_paine26 =[ $paine26, zombie_paine27 ] {ai_painforward(3);};
|
||||
void() zombie_paine27 =[ $paine27, zombie_paine28 ] {ai_painforward(1);};
|
||||
void() zombie_paine28 =[ $paine28, zombie_paine29 ] {ai_pain(1);};
|
||||
void() zombie_paine29 =[ $paine29, zombie_paine30 ] {};
|
||||
void() zombie_paine30 =[ $paine30, zombie_run1 ] {};
|
||||
|
||||
void(entity inflictor, entity attacker) zombie_die =
|
||||
{
|
||||
SpawnGib("progs/gib1.mdl");
|
||||
SpawnGib("progs/gib2.mdl");
|
||||
SpawnGib("progs/gib3.mdl");
|
||||
SpawnGib("progs/gib4.mdl");
|
||||
SpawnGib("progs/gib5.mdl");
|
||||
SpawnGib("progs/blood.mdl");
|
||||
SpawnGib("progs/blood.mdl");
|
||||
BecomeGibs();
|
||||
};
|
||||
|
||||
/*
|
||||
=================
|
||||
zombie_pain
|
||||
|
||||
Zombies can only be killed (gibbed) by doing 60 hit points of damage
|
||||
in a single frame (rockets, grenades, quad shotgun, quad nailgun).
|
||||
|
||||
A hit of 25 points or more (super shotgun, quad nailgun) will allways put it
|
||||
down to the ground.
|
||||
|
||||
A hit of from 10 to 40 points in one frame will cause it to go down if it
|
||||
has been twice in two seconds, otherwise it goes into one of the four
|
||||
fast pain frames.
|
||||
|
||||
A hit of less than 10 points of damage (winged by a shotgun) will be ignored.
|
||||
|
||||
FIXME: don't use pain_finished because of nightmare hack
|
||||
=================
|
||||
*/
|
||||
void(entity attacker, float take) zombie_pain =
|
||||
{
|
||||
local float r;
|
||||
|
||||
self.health = 60; // allways reset health
|
||||
|
||||
if (take < 9)
|
||||
return; // totally ignore
|
||||
|
||||
if (self.inpain == 2)
|
||||
return; // down on ground, so don't reset any counters
|
||||
|
||||
// go down immediately if a big enough hit
|
||||
if (take >= 25)
|
||||
{
|
||||
self.inpain = 2;
|
||||
zombie_paine1 ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.inpain)
|
||||
{
|
||||
// if hit again in next gre seconds while not in pain frames, definately drop
|
||||
self.pain_finished = time + 3;
|
||||
return; // currently going through an animation, don't change
|
||||
}
|
||||
|
||||
if (self.pain_finished > time)
|
||||
{
|
||||
// hit again, so drop down
|
||||
self.inpain = 2;
|
||||
zombie_paine1 ();
|
||||
return;
|
||||
}
|
||||
|
||||
// gp into one of the fast pain animations
|
||||
self.inpain = 1;
|
||||
|
||||
r = random();
|
||||
if (r < 0.25)
|
||||
zombie_paina1 ();
|
||||
else if (r < 0.5)
|
||||
zombie_painb1 ();
|
||||
else if (r < 0.75)
|
||||
zombie_painc1 ();
|
||||
else
|
||||
zombie_paind1 ();
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
/*QUAKED monster_zombie (1 0 0) (-16 -16 -24) (16 16 32) CRUCIFIED AMBUSH TELEPORT X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD
|
||||
{
|
||||
model ( {{ spawnflags & 2 -> { "path" : "progs/zombie.mdl", "frame" : 192 }, "progs/zombie.mdl" }} );
|
||||
}
|
||||
Zombie.
|
||||
*/
|
||||
void() monster_zombie =
|
||||
{
|
||||
if (deathmatch)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
precache_model ("progs/zombie.mdl");
|
||||
precache_model ("progs/h_zombie.mdl");
|
||||
precache_model ("progs/zom_gib.mdl");
|
||||
|
||||
precache_sound ("zombie/z_idle.wav");
|
||||
precache_sound ("zombie/z_idle1.wav");
|
||||
precache_sound ("zombie/z_shot1.wav");
|
||||
precache_sound ("zombie/z_gib.wav");
|
||||
precache_sound ("zombie/z_pain.wav");
|
||||
precache_sound ("zombie/z_pain1.wav");
|
||||
precache_sound ("zombie/z_fall.wav");
|
||||
precache_sound ("zombie/z_miss.wav");
|
||||
precache_sound ("zombie/z_hit.wav");
|
||||
precache_sound ("zombie/idle_w2.wav");
|
||||
|
||||
if (self.spawnflags & ZOMBIE_CRUCIFIED)
|
||||
{
|
||||
self.spawnflags = self.spawnflags - ZOMBIE_CRUCIFIED;
|
||||
self.solid = SOLID_NOT;
|
||||
self.movetype = MOVETYPE_NONE;
|
||||
setmodel (self, "progs/zombie.mdl");
|
||||
setsize (self, '-16 -16 -24', '16 16 40');
|
||||
zombie_cruc1();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self.spawnflags & ZOMBIE_AMBUSH)
|
||||
self.spawnflags = self.spawnflags - ZOMBIE_AMBUSH + MONSTER_AMBUSH;
|
||||
self.th_stand = zombie_stand1;
|
||||
self.th_walk = zombie_walk1;
|
||||
self.th_run = zombie_run1;
|
||||
self.th_pain = zombie_pain;
|
||||
self.th_die = zombie_die;
|
||||
self.th_missile = zombie_missile;
|
||||
monster_start("progs/zombie.mdl", "progs/h_zombie.mdl", 60, 0, '-16 -16 -24', '16 16 40');
|
||||
}
|
||||
};
|
||||
266
mod_slipgate/source/server/obituary.qc
Normal file
266
mod_slipgate/source/server/obituary.qc
Normal file
@@ -0,0 +1,266 @@
|
||||
/*==========
|
||||
Obituary
|
||||
==========*/
|
||||
void(entity targ, entity attacker, entity inflictor) Obituary =
|
||||
{
|
||||
string deathstring, deathstring2;
|
||||
float rnum = random();
|
||||
|
||||
// regular telefrag
|
||||
if (attacker.classname == "teledeath")
|
||||
{
|
||||
bprint (targ.netname);
|
||||
bprint (" was telefragged by ");
|
||||
bprint (attacker.owner.netname);
|
||||
bprint ("\n");
|
||||
|
||||
attacker.owner.frags = attacker.owner.frags + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// inverse pentagram telefrag
|
||||
if (attacker.classname == "teledeath2")
|
||||
{
|
||||
bprint ("Satan's power deflects ");
|
||||
bprint (targ.netname);
|
||||
bprint ("'s telefrag\n");
|
||||
|
||||
targ.frags = targ.frags - 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// double pentagram telefrag
|
||||
if (attacker.classname == "teledeath3")
|
||||
{
|
||||
bprint (targ.netname);
|
||||
bprint (" was telefragged by ");
|
||||
bprint (attacker.owner.netname);
|
||||
bprint ("'s Satan power\n");
|
||||
|
||||
attacker.owner.frags = attacker.owner.frags + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (attacker.classname == "player")
|
||||
{
|
||||
// killed self
|
||||
if (targ == attacker)
|
||||
{
|
||||
attacker.frags = attacker.frags - 1;
|
||||
bprint (targ.netname);
|
||||
|
||||
if (targ.weapon == IT_LIGHTNING && targ.waterlevel > 1)
|
||||
{
|
||||
bprint (" discharges into the water.\n");
|
||||
return;
|
||||
}
|
||||
if (inflictor.classname == "grenade")
|
||||
bprint (" tries to put the pin back in\n");
|
||||
else
|
||||
bprint (" becomes bored with life\n");
|
||||
return;
|
||||
}
|
||||
// killed a team mate
|
||||
else if ( (teamplay == 2) && (targ.team > 0) && (targ.team == attacker.team) )
|
||||
{
|
||||
bprint (attacker.netname);
|
||||
|
||||
if (rnum < 0.25)
|
||||
deathstring = " mows down a teammate\n";
|
||||
else if (rnum < 0.50)
|
||||
deathstring = " checks his glasses\n";
|
||||
else if (rnum < 0.75)
|
||||
deathstring = " gets a frag for the other team\n";
|
||||
else
|
||||
deathstring = " loses another friend\n";
|
||||
|
||||
bprint (deathstring);
|
||||
attacker.frags = attacker.frags - 1;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
attacker.frags = attacker.frags + 1;
|
||||
|
||||
rnum = attacker.weapon;
|
||||
if (rnum == IT_AXE)
|
||||
{
|
||||
deathstring = " was ax-murdered by ";
|
||||
deathstring2 = "\n";
|
||||
}
|
||||
if (rnum == IT_SHOTGUN)
|
||||
{
|
||||
deathstring = " chewed on ";
|
||||
deathstring2 = "'s boomstick\n";
|
||||
}
|
||||
if (rnum == IT_SUPER_SHOTGUN)
|
||||
{
|
||||
deathstring = " ate 2 loads of ";
|
||||
deathstring2 = "'s buckshot\n";
|
||||
}
|
||||
if (rnum == IT_NAILGUN)
|
||||
{
|
||||
deathstring = " was nailed by ";
|
||||
deathstring2 = "\n";
|
||||
}
|
||||
if (rnum == IT_SUPER_NAILGUN)
|
||||
{
|
||||
deathstring = " was punctured by ";
|
||||
deathstring2 = "\n";
|
||||
}
|
||||
if (rnum == IT_GRENADE_LAUNCHER)
|
||||
{
|
||||
deathstring = " eats ";
|
||||
deathstring2 = "'s pineapple\n";
|
||||
if (targ.health < -40)
|
||||
{
|
||||
deathstring = " was gibbed by ";
|
||||
deathstring2 = "'s grenade\n";
|
||||
}
|
||||
}
|
||||
if (rnum == IT_ROCKET_LAUNCHER)
|
||||
{
|
||||
deathstring = " rides ";
|
||||
deathstring2 = "'s rocket\n";
|
||||
if (targ.health < -40)
|
||||
{
|
||||
deathstring = " was gibbed by ";
|
||||
deathstring2 = "'s rocket\n" ;
|
||||
}
|
||||
}
|
||||
if (rnum == IT_LIGHTNING)
|
||||
{
|
||||
deathstring = " accepts ";
|
||||
if (attacker.waterlevel > 1)
|
||||
deathstring2 = "'s discharge\n";
|
||||
else
|
||||
deathstring2 = "'s shaft\n";
|
||||
}
|
||||
bprint (targ.netname);
|
||||
bprint (deathstring);
|
||||
bprint (attacker.netname);
|
||||
bprint (deathstring2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
targ.frags = targ.frags - 1;
|
||||
bprint (targ.netname);
|
||||
|
||||
// killed by a monster?
|
||||
if (attacker.flags & FL_MONSTER)
|
||||
{
|
||||
if (attacker.classname == "monster_army")
|
||||
bprint (" was shot by a Grunt\n");
|
||||
if (attacker.classname == "monster_boss")
|
||||
bprint (" became one with Chthon\n");
|
||||
if (attacker.classname == "monster_demon1")
|
||||
bprint (" was eviscerated by a Fiend\n");
|
||||
if (attacker.classname == "monster_dog")
|
||||
bprint (" was mauled by a Rottweiler\n");
|
||||
if (attacker.classname == "monster_enforcer")
|
||||
bprint (" was blasted by an Enforcer\n");
|
||||
if (attacker.classname == "monster_fish")
|
||||
bprint (" was fed to the Rotfish\n");
|
||||
if (attacker.classname == "monster_hell_knight")
|
||||
bprint (" was slain by a Death Knight\n");
|
||||
if (attacker.classname == "monster_knight")
|
||||
bprint (" was slashed by a Knight\n");
|
||||
if (attacker.classname == "monster_ogre")
|
||||
bprint (" was destroyed by an Ogre\n");
|
||||
if (attacker.classname == "monster_shalrath")
|
||||
bprint (" was exploded by a Vore\n");
|
||||
if (attacker.classname == "monster_shambler")
|
||||
bprint (" was smashed by a Shambler\n");
|
||||
if (attacker.classname == "monster_tarbaby")
|
||||
bprint (" was slimed by a Spawn\n");
|
||||
if (attacker.classname == "monster_wizard")
|
||||
bprint (" was scragged by a Scrag\n");
|
||||
if (attacker.classname == "monster_zombie")
|
||||
bprint (" joins the Zombies\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// tricks and traps
|
||||
if (attacker.classname == "explobox")
|
||||
{
|
||||
bprint (" blew up\n");
|
||||
return;
|
||||
}
|
||||
if (attacker.solid == SOLID_BSP && attacker != world)
|
||||
{
|
||||
bprint (" was squished\n");
|
||||
return;
|
||||
}
|
||||
if (attacker.classname == "trap_shooter" || attacker.classname == "trap_spikeshooter")
|
||||
{
|
||||
bprint (" was spiked\n");
|
||||
return;
|
||||
}
|
||||
if (attacker.classname == "fireball")
|
||||
{
|
||||
bprint (" ate a lavaball\n");
|
||||
return;
|
||||
}
|
||||
if (attacker.classname == "trigger_changelevel")
|
||||
{
|
||||
bprint (" tried to leave\n");
|
||||
return;
|
||||
}
|
||||
if (attacker.classname == "trigger_hurt")
|
||||
{
|
||||
bprint (" was in the wrong place at the wrong time\n");
|
||||
return;
|
||||
}
|
||||
if (attacker.classname == "trigger_void")
|
||||
{
|
||||
bprint (" touched the void\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// in-water deaths
|
||||
rnum = targ.watertype;
|
||||
if (rnum == CONTENT_WATER)
|
||||
{
|
||||
if (random() < 0.5)
|
||||
bprint (" sleeps with the fishes\n");
|
||||
else
|
||||
bprint (" sucks it down\n");
|
||||
return;
|
||||
}
|
||||
else if (rnum == CONTENT_SLIME)
|
||||
{
|
||||
if (random() < 0.5)
|
||||
bprint (" gulped a load of slime\n");
|
||||
else
|
||||
bprint (" can't exist on slime alone\n");
|
||||
return;
|
||||
}
|
||||
else if (rnum == CONTENT_LAVA)
|
||||
{
|
||||
if (targ.health < -15)
|
||||
{
|
||||
bprint (" burst into flames\n");
|
||||
return;
|
||||
}
|
||||
if (random() < 0.5)
|
||||
bprint (" turned into hot slag\n");
|
||||
else
|
||||
bprint (" visits the Volcano God\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// fell to their death?
|
||||
if (targ.deathtype == "falling")
|
||||
{
|
||||
targ.deathtype = "";
|
||||
bprint (" fell to his death\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// hell if I know; he's just dead!!!
|
||||
bprint (" died\n");
|
||||
}
|
||||
};
|
||||
220
mod_slipgate/source/server/plats.qc
Normal file
220
mod_slipgate/source/server/plats.qc
Normal file
@@ -0,0 +1,220 @@
|
||||
static enumflags { PLAT_LOW_TRIGGER };
|
||||
|
||||
/*==========
|
||||
plat_hit_bottom
|
||||
==========*/
|
||||
static void() plat_hit_bottom =
|
||||
{
|
||||
sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
|
||||
self.state = STATE_BOTTOM;
|
||||
};
|
||||
|
||||
/*==========
|
||||
plat_go_down
|
||||
==========*/
|
||||
static void() plat_go_down =
|
||||
{
|
||||
sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
|
||||
self.state = STATE_DOWN;
|
||||
SUB_CalcMove (self.pos2, self.speed, plat_hit_bottom);
|
||||
};
|
||||
|
||||
/*==========
|
||||
plat_hit_top
|
||||
==========*/
|
||||
static void() plat_hit_top =
|
||||
{
|
||||
sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
|
||||
self.state = STATE_TOP;
|
||||
self.think = plat_go_down;
|
||||
self.nextthink = self.ltime + self.wait;
|
||||
};
|
||||
|
||||
/*==========
|
||||
plat_go_up
|
||||
==========*/
|
||||
static void() plat_go_up =
|
||||
{
|
||||
sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
|
||||
self.state = STATE_UP;
|
||||
SUB_CalcMove (self.pos1, self.speed, plat_hit_top);
|
||||
};
|
||||
|
||||
/*==========
|
||||
plat_use
|
||||
==========*/
|
||||
static void() plat_use =
|
||||
{
|
||||
self.use = SUB_Null;
|
||||
plat_go_down();
|
||||
};
|
||||
|
||||
/*==========
|
||||
plat_crush
|
||||
|
||||
something has blocked the plat -
|
||||
cause some damage and reverse the plats movement
|
||||
==========*/
|
||||
static void() plat_crush =
|
||||
{
|
||||
Damage(other, self, self, self.dmg);
|
||||
|
||||
if (self.state == STATE_UP)
|
||||
plat_go_down ();
|
||||
else if (self.state == STATE_DOWN)
|
||||
plat_go_up ();
|
||||
};
|
||||
|
||||
/*==========
|
||||
plat_trigger_touch
|
||||
|
||||
when the trigger field is touched, the plat moves to the "up" position
|
||||
==========*/
|
||||
static void() plat_trigger_touch =
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
if (other.health <= 0)
|
||||
return;
|
||||
if (self.owner.use == plat_use) // plat has a targetname and is still waiting to be triggered
|
||||
return;
|
||||
|
||||
self = self.owner;
|
||||
if (self.state == STATE_BOTTOM)
|
||||
plat_go_up();
|
||||
else if (self.state == STATE_TOP)
|
||||
self.nextthink = self.ltime + 1; // delay going down if player is stood on the plat
|
||||
};
|
||||
|
||||
/*==========
|
||||
plat_spawn_trigger
|
||||
|
||||
spawn a trigger that activates the plat when touched
|
||||
plats are never activated directly by touching the plat itself
|
||||
==========*/
|
||||
static void() plat_spawn_trigger =
|
||||
{
|
||||
entity trigger = spawn();
|
||||
trigger.classname = "func_plat_trigger";
|
||||
trigger.owner = self;
|
||||
self.trigger_field = trigger;
|
||||
trigger.touch = plat_trigger_touch;
|
||||
trigger.movetype = MOVETYPE_NONE;
|
||||
trigger.solid = SOLID_TRIGGER;
|
||||
|
||||
vector tmin, tmax;
|
||||
tmin = self.mins + [25, 25, self.lip];
|
||||
tmax = self.maxs - [25, 25, -self.lip];
|
||||
if (self.spawnflags & PLAT_LOW_TRIGGER)
|
||||
tmax_z = tmin_z + self.lip;
|
||||
|
||||
if (self.size_x <= 50)
|
||||
{
|
||||
tmin_x = self.mins_x;
|
||||
tmax_x = self.maxs_x;
|
||||
}
|
||||
if (self.size_y <= 50)
|
||||
{
|
||||
tmin_y = self.mins_y;
|
||||
tmax_y = self.maxs_y;
|
||||
}
|
||||
setsize (trigger, tmin, tmax);
|
||||
};
|
||||
|
||||
/*QUAKED func_plat (0 .5 .8) ? LOW_TRIGGER X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
A platform that moves vertically up and down.
|
||||
|
||||
Plats are always drawn in the map editor in the "up" position, so they will light correctly.
|
||||
They are then moved to the down position on map load.
|
||||
|
||||
Plats spawn a trigger field that cause the plat to rise when a player touches it. By default
|
||||
this trigger field spans the entire height of the plat. The plat will stay in the up position as
|
||||
long as the player is touching the trigger and will fall again when they step off.
|
||||
|
||||
The plat will move a distance of its "height" minus any "lip".
|
||||
|
||||
If the plat has a "targetname", it will start disabled in the up position until
|
||||
it is triggered, when it will lower and behave like a normal plat.
|
||||
|
||||
Spawnflags:
|
||||
LOW_TRIGGER - the plat trigger field is spawned only at the bottom of the plat.
|
||||
|
||||
Keys:
|
||||
"dmg" - damage to deal if blocked. default 1.
|
||||
"speed" - speed of movement. default 150.
|
||||
"lip" - amount of height to leave at end of move. this should usually be
|
||||
the height of the component of your plat that a player can step upon. default 8.
|
||||
"height" - override the movement distance, which by default
|
||||
is calculated from the height of the actual brush minus any lip.
|
||||
"wait" - time to wait at top before returning. default 3.
|
||||
"sounds" -
|
||||
-1) custom, see below
|
||||
0) chain slow
|
||||
1) base fast
|
||||
2) chain slow (default)
|
||||
3) base alternative
|
||||
"noise" - sound to play at start of plat movement. tip: can contain looped segments.
|
||||
"noise1" - sound to play at end of plat movement.
|
||||
*/
|
||||
void() func_plat =
|
||||
{
|
||||
self.solid = SOLID_BSP;
|
||||
self.movetype = MOVETYPE_PUSH;
|
||||
setmodel (self, self.model);
|
||||
|
||||
// sounds
|
||||
// -1 custom, 1 = base, 2 = medieval (default), 3 = base alternative
|
||||
SetFloatDefault(sounds, 2);
|
||||
if (self.sounds == 1)
|
||||
{
|
||||
self.noise = "plats/plat1.wav";
|
||||
self.noise1 = "plats/plat2.wav";
|
||||
}
|
||||
else if (self.sounds == 2)
|
||||
{
|
||||
self.noise = "plats/medplat1.wav";
|
||||
self.noise1 = "plats/medplat2.wav";
|
||||
}
|
||||
else if (self.sounds == 3)
|
||||
{
|
||||
self.noise = "plats/plat3.wav";
|
||||
self.noise1 = "plats/plat4.wav";
|
||||
}
|
||||
if (!self.noise || !self.noise1)
|
||||
{
|
||||
objerror("noise and noise1 must be set for custom sound\n");
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
precache_sound(self.noise);
|
||||
precache_sound(self.noise1);
|
||||
|
||||
// defaults
|
||||
SetPositiveDefault(dmg, 1);
|
||||
SetPositiveDefault(speed, 150);
|
||||
SetPositiveDefault(lip, 8);
|
||||
SetPositiveDefault(wait, 3);
|
||||
SetFloatDefault(height, self.size_z - self.lip);
|
||||
|
||||
self.blocked = plat_crush;
|
||||
|
||||
// pos1 is the top position, pos2 is the bottom
|
||||
self.pos1 = self.origin;
|
||||
self.pos2 = self.origin;
|
||||
self.pos2_z = self.pos2_z - self.height;
|
||||
plat_spawn_trigger();
|
||||
|
||||
// if a plat has a targetname, the
|
||||
// plat must be triggered to lower it
|
||||
if (self.targetname != "")
|
||||
{
|
||||
self.use = plat_use;
|
||||
self.state = STATE_TOP;
|
||||
setorigin (self, self.pos1);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.state = STATE_BOTTOM;
|
||||
setorigin (self, self.pos2);
|
||||
}
|
||||
};
|
||||
516
mod_slipgate/source/server/player.qc
Normal file
516
mod_slipgate/source/server/player.qc
Normal file
@@ -0,0 +1,516 @@
|
||||
$frame axrun1 axrun2 axrun3 axrun4 axrun5 axrun6
|
||||
|
||||
$frame rockrun1 rockrun2 rockrun3 rockrun4 rockrun5 rockrun6
|
||||
|
||||
$frame stand1 stand2 stand3 stand4 stand5
|
||||
|
||||
$frame axstnd1 axstnd2 axstnd3 axstnd4 axstnd5 axstnd6
|
||||
$frame axstnd7 axstnd8 axstnd9 axstnd10 axstnd11 axstnd12
|
||||
|
||||
$frame axpain1 axpain2 axpain3 axpain4 axpain5 axpain6
|
||||
|
||||
$frame pain1 pain2 pain3 pain4 pain5 pain6
|
||||
|
||||
$frame axdeth1 axdeth2 axdeth3 axdeth4 axdeth5 axdeth6
|
||||
$frame axdeth7 axdeth8 axdeth9
|
||||
|
||||
$frame deatha1 deatha2 deatha3 deatha4 deatha5 deatha6 deatha7 deatha8
|
||||
$frame deatha9 deatha10 deatha11
|
||||
|
||||
$frame deathb1 deathb2 deathb3 deathb4 deathb5 deathb6 deathb7 deathb8
|
||||
$frame deathb9
|
||||
|
||||
$frame deathc1 deathc2 deathc3 deathc4 deathc5 deathc6 deathc7 deathc8
|
||||
$frame deathc9 deathc10 deathc11 deathc12 deathc13 deathc14 deathc15
|
||||
|
||||
$frame deathd1 deathd2 deathd3 deathd4 deathd5 deathd6 deathd7
|
||||
$frame deathd8 deathd9
|
||||
|
||||
$frame deathe1 deathe2 deathe3 deathe4 deathe5 deathe6 deathe7
|
||||
$frame deathe8 deathe9
|
||||
|
||||
$frame nailatt1 nailatt2
|
||||
|
||||
$frame light1 light2
|
||||
|
||||
$frame rockatt1 rockatt2 rockatt3 rockatt4 rockatt5 rockatt6
|
||||
|
||||
$frame shotatt1 shotatt2 shotatt3 shotatt4 shotatt5 shotatt6
|
||||
|
||||
$frame axatt1 axatt2 axatt3 axatt4 axatt5 axatt6
|
||||
|
||||
$frame axattb1 axattb2 axattb3 axattb4 axattb5 axattb6
|
||||
|
||||
$frame axattc1 axattc2 axattc3 axattc4 axattc5 axattc6
|
||||
|
||||
$frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
|
||||
|
||||
void() player_run;
|
||||
|
||||
/*==========
|
||||
player_stand
|
||||
==========*/
|
||||
void() player_stand =
|
||||
{
|
||||
self.weaponframe = 0;
|
||||
if (self.velocity_x || self.velocity_y)
|
||||
{
|
||||
player_run();
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.weapon == IT_AXE)
|
||||
{
|
||||
if (self.walkframe >= 12)
|
||||
self.walkframe = 0;
|
||||
self.frame = $axstnd1 + self.walkframe;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self.walkframe >= 5)
|
||||
self.walkframe = 0;
|
||||
self.frame = $stand1 + self.walkframe;
|
||||
}
|
||||
self.walkframe = self.walkframe + 1;
|
||||
|
||||
self.think = player_stand;
|
||||
self.nextthink = time + 0.1;
|
||||
};
|
||||
|
||||
/*==========
|
||||
player_run
|
||||
==========*/
|
||||
void() player_run =
|
||||
{
|
||||
self.weaponframe = 0;
|
||||
if (!self.velocity_x && !self.velocity_y)
|
||||
{
|
||||
player_stand();
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.weapon == IT_AXE)
|
||||
{
|
||||
if (self.walkframe >= 6)
|
||||
self.walkframe = 0;
|
||||
self.frame = $axrun1 + self.walkframe;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self.walkframe >= 6)
|
||||
self.walkframe = 0;
|
||||
self.frame = $rockrun1 + self.walkframe;
|
||||
}
|
||||
self.walkframe = self.walkframe + 1;
|
||||
|
||||
self.think = player_run;
|
||||
self.nextthink = time + 0.1;
|
||||
};
|
||||
|
||||
void() player_axe1 = [$axatt1, player_axe2 ] {self.weaponframe=1;};
|
||||
void() player_axe2 = [$axatt2, player_axe3 ] {self.weaponframe=2;};
|
||||
void() player_axe3 = [$axatt3, player_axe4 ] {self.weaponframe=3;W_FireAxe();};
|
||||
void() player_axe4 = [$axatt4, player_run ] {self.weaponframe=4;};
|
||||
|
||||
void() player_axeb1 = [$axattb1, player_axeb2 ] {self.weaponframe=5;};
|
||||
void() player_axeb2 = [$axattb2, player_axeb3 ] {self.weaponframe=6;};
|
||||
void() player_axeb3 = [$axattb3, player_axeb4 ] {self.weaponframe=7;W_FireAxe();};
|
||||
void() player_axeb4 = [$axattb4, player_run ] {self.weaponframe=8;};
|
||||
|
||||
void() player_axec1 = [$axattc1, player_axec2 ] {self.weaponframe=1;};
|
||||
void() player_axec2 = [$axattc2, player_axec3 ] {self.weaponframe=2;};
|
||||
void() player_axec3 = [$axattc3, player_axec4 ] {self.weaponframe=3;W_FireAxe();};
|
||||
void() player_axec4 = [$axattc4, player_run ] {self.weaponframe=4;};
|
||||
|
||||
void() player_axed1 = [$axattd1, player_axed2 ] {self.weaponframe=5;};
|
||||
void() player_axed2 = [$axattd2, player_axed3 ] {self.weaponframe=6;};
|
||||
void() player_axed3 = [$axattd3, player_axed4 ] {self.weaponframe=7;W_FireAxe();};
|
||||
void() player_axed4 = [$axattd4, player_run ] {self.weaponframe=8;};
|
||||
|
||||
void() player_shot1 = [$shotatt1, player_shot2 ] {self.weaponframe=1;self.effects = self.effects | EF_MUZZLEFLASH;};
|
||||
void() player_shot2 = [$shotatt2, player_shot3 ] {self.weaponframe=2;};
|
||||
void() player_shot3 = [$shotatt3, player_shot4 ] {self.weaponframe=3;};
|
||||
void() player_shot4 = [$shotatt4, player_shot5 ] {self.weaponframe=4;};
|
||||
void() player_shot5 = [$shotatt5, player_shot6 ] {self.weaponframe=5;};
|
||||
void() player_shot6 = [$shotatt6, player_run ] {self.weaponframe=6;};
|
||||
|
||||
/*==========
|
||||
player_nail
|
||||
==========*/
|
||||
void() player_nail =
|
||||
{
|
||||
if (!self.button0)
|
||||
{
|
||||
player_run();
|
||||
return;
|
||||
}
|
||||
|
||||
self.effects = self.effects | EF_MUZZLEFLASH;
|
||||
self.weaponframe = self.weaponframe + 1;
|
||||
if (self.weaponframe > 8)
|
||||
self.weaponframe = 1;
|
||||
W_QuadDamageSound();
|
||||
if (self.frame == $nailatt1)
|
||||
{
|
||||
self.frame = $nailatt2;
|
||||
W_FireSpikes(-4);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.frame = $nailatt1;
|
||||
W_FireSpikes(4);
|
||||
}
|
||||
self.attack_finished = time + 0.2;
|
||||
|
||||
self.think = player_nail;
|
||||
self.nextthink = time + 0.1;
|
||||
};
|
||||
|
||||
void() player_rocket1 =[$rockatt1, player_rocket2 ] {self.weaponframe=1;self.effects = self.effects | EF_MUZZLEFLASH;};
|
||||
void() player_rocket2 =[$rockatt2, player_rocket3 ] {self.weaponframe=2;};
|
||||
void() player_rocket3 =[$rockatt3, player_rocket4 ] {self.weaponframe=3;};
|
||||
void() player_rocket4 =[$rockatt4, player_rocket5 ] {self.weaponframe=4;};
|
||||
void() player_rocket5 =[$rockatt5, player_rocket6 ] {self.weaponframe=5;};
|
||||
void() player_rocket6 =[$rockatt6, player_run ] {self.weaponframe=6;};
|
||||
|
||||
/*==========
|
||||
player_lightning
|
||||
==========*/
|
||||
void() player_lightning =
|
||||
{
|
||||
if (!self.button0)
|
||||
{
|
||||
player_run();
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.frame == $light1)
|
||||
self.frame = $light2;
|
||||
else
|
||||
self.frame = $light1;
|
||||
|
||||
self.effects = self.effects | EF_MUZZLEFLASH;
|
||||
self.weaponframe = self.weaponframe + 1;
|
||||
if (self.weaponframe > 4)
|
||||
self.weaponframe = 1;
|
||||
W_QuadDamageSound();
|
||||
W_FireLightning();
|
||||
self.attack_finished = time + 0.2;
|
||||
|
||||
self.think = player_lightning;
|
||||
self.nextthink = time + 0.1;
|
||||
};
|
||||
|
||||
/*==========
|
||||
PlayerDeathBubblesSpawn
|
||||
==========*/
|
||||
static void() PlayerDeathBubblesSpawn =
|
||||
{
|
||||
if (self.owner.waterlevel != 3)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
if (self.count <= 0)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
|
||||
self.count = self.count - 1;
|
||||
self.think = PlayerDeathBubblesSpawn;
|
||||
self.nextthink = time + 0.01;
|
||||
|
||||
entity bubble = spawn();
|
||||
bubble.classname = "bubble";
|
||||
bubble.owner = self.owner;
|
||||
bubble.solid = SOLID_NOT;
|
||||
bubble.movetype = MOVETYPE_NOCLIP;
|
||||
setmodel (bubble, "progs/s_bubble.spr");
|
||||
setsize (bubble, '-8 -8 -8', '8 8 8');
|
||||
setorigin (bubble, self.owner.origin + self.owner.view_ofs);
|
||||
bubble.velocity = '0 0 15';
|
||||
bubble.think = bubble_bob;
|
||||
bubble.nextthink = time + 0.5;
|
||||
};
|
||||
|
||||
/*==========
|
||||
PlayerDeathBubbles
|
||||
==========*/
|
||||
static void(float num) PlayerDeathBubbles =
|
||||
{
|
||||
entity e = spawn();
|
||||
e.classname = "bubblespawner";
|
||||
e.owner = self;
|
||||
setorigin (e, self.origin);
|
||||
e.movetype = MOVETYPE_NONE;
|
||||
e.solid = SOLID_NOT;
|
||||
e.count = num;
|
||||
e.think = PlayerDeathBubblesSpawn;
|
||||
e.nextthink = time + 0.01;
|
||||
};
|
||||
|
||||
/*==========
|
||||
PlayerPainSound
|
||||
==========*/
|
||||
void(entity attacker) PlayerPainSound =
|
||||
{
|
||||
// liquid pain sounds
|
||||
if (self.watertype == CONTENT_WATER)
|
||||
{
|
||||
if (self.waterlevel == 3)
|
||||
{
|
||||
PlayerDeathBubbles(1);
|
||||
if (random() < 0.5)
|
||||
sound (self, CHAN_VOICE, "player/drown1.wav", 1, ATTN_NORM);
|
||||
else
|
||||
sound (self, CHAN_VOICE, "player/drown2.wav", 1, ATTN_NORM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (self.watertype == CONTENT_SLIME)
|
||||
{
|
||||
if (random() < 0.5)
|
||||
sound (self, CHAN_VOICE, "player/lburn1.wav", 1, ATTN_NORM);
|
||||
else
|
||||
sound (self, CHAN_VOICE, "player/lburn2.wav", 1, ATTN_NORM);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.watertype == CONTENT_LAVA)
|
||||
{
|
||||
if (random() < 0.5)
|
||||
sound (self, CHAN_VOICE, "player/lburn1.wav", 1, ATTN_NORM);
|
||||
else
|
||||
sound (self, CHAN_VOICE, "player/lburn2.wav", 1, ATTN_NORM);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.pain_finished > time)
|
||||
return;
|
||||
self.pain_finished = time + 0.5;
|
||||
|
||||
/*if (self.axhitme == 1)
|
||||
{
|
||||
self.axhitme = 0;
|
||||
sound (self, CHAN_VOICE, "player/axhit1.wav", 1, ATTN_NORM);
|
||||
return;
|
||||
}*/
|
||||
|
||||
float r = randomrange(6);
|
||||
if (r == 0)
|
||||
sound (self, CHAN_VOICE, "player/pain1.wav", 1, ATTN_NORM);
|
||||
else if (r == 1)
|
||||
sound (self, CHAN_VOICE, "player/pain2.wav", 1, ATTN_NORM);
|
||||
else if (r == 2)
|
||||
sound (self, CHAN_VOICE, "player/pain3.wav", 1, ATTN_NORM);
|
||||
else if (r == 3)
|
||||
sound (self, CHAN_VOICE, "player/pain4.wav", 1, ATTN_NORM);
|
||||
else if (r == 4)
|
||||
sound (self, CHAN_VOICE, "player/pain5.wav", 1, ATTN_NORM);
|
||||
else
|
||||
sound (self, CHAN_VOICE, "player/pain6.wav", 1, ATTN_NORM);
|
||||
};
|
||||
|
||||
void() player_pain1 = [ $pain1, player_pain2 ] {};
|
||||
void() player_pain2 = [ $pain2, player_pain3 ] {};
|
||||
void() player_pain3 = [ $pain3, player_pain4 ] {};
|
||||
void() player_pain4 = [ $pain4, player_pain5 ] {};
|
||||
void() player_pain5 = [ $pain5, player_pain6 ] {};
|
||||
void() player_pain6 = [ $pain6, player_run ] {};
|
||||
|
||||
void() player_axpain1 = [ $axpain1, player_axpain2 ] {};
|
||||
void() player_axpain2 = [ $axpain2, player_axpain3 ] {};
|
||||
void() player_axpain3 = [ $axpain3, player_axpain4 ] {};
|
||||
void() player_axpain4 = [ $axpain4, player_axpain5 ] {};
|
||||
void() player_axpain5 = [ $axpain5, player_axpain6 ] {};
|
||||
void() player_axpain6 = [ $axpain6, player_run ] {};
|
||||
|
||||
/*==========
|
||||
player_pain
|
||||
==========*/
|
||||
void(entity attacker, float damage) player_pain =
|
||||
{
|
||||
if (self.weaponframe)
|
||||
return;
|
||||
if (self.items & IT_INVISIBILITY)
|
||||
return;
|
||||
|
||||
PlayerPainSound(attacker);
|
||||
if (self.weapon == IT_AXE)
|
||||
player_axpain1 ();
|
||||
else
|
||||
player_pain1 ();
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*==========
|
||||
PlayerDeathSound
|
||||
==========*/
|
||||
static void() PlayerDeathSound =
|
||||
{
|
||||
// water death sounds
|
||||
if (self.waterlevel == 3)
|
||||
{
|
||||
PlayerDeathBubbles(20);
|
||||
sound (self, CHAN_VOICE, "player/h2odeath.wav", 1, ATTN_NONE);
|
||||
return;
|
||||
}
|
||||
|
||||
float r = randomrange(5);
|
||||
if (r == 0)
|
||||
self.noise = "player/death1.wav";
|
||||
else if (r == 1)
|
||||
self.noise = "player/death2.wav";
|
||||
else if (r == 2)
|
||||
self.noise = "player/death3.wav";
|
||||
else if (r == 3)
|
||||
self.noise = "player/death4.wav";
|
||||
else
|
||||
self.noise = "player/death5.wav";
|
||||
|
||||
sound (self, CHAN_VOICE, self.noise, 1, ATTN_NONE);
|
||||
};
|
||||
|
||||
/*==========
|
||||
PlayerDead
|
||||
==========*/
|
||||
static void() PlayerDead =
|
||||
{
|
||||
self.think = SUB_Null;
|
||||
self.nextthink = -1;
|
||||
self.deadflag = DEAD_DEAD;
|
||||
};
|
||||
|
||||
void() player_diea1 = [ $deatha1, player_diea2 ] {};
|
||||
void() player_diea2 = [ $deatha2, player_diea3 ] {};
|
||||
void() player_diea3 = [ $deatha3, player_diea4 ] {};
|
||||
void() player_diea4 = [ $deatha4, player_diea5 ] {};
|
||||
void() player_diea5 = [ $deatha5, player_diea6 ] {};
|
||||
void() player_diea6 = [ $deatha6, player_diea7 ] {};
|
||||
void() player_diea7 = [ $deatha7, player_diea8 ] {};
|
||||
void() player_diea8 = [ $deatha8, player_diea9 ] {};
|
||||
void() player_diea9 = [ $deatha9, player_diea10 ] {};
|
||||
void() player_diea10 = [ $deatha10, player_diea11 ] {};
|
||||
void() player_diea11 = [ $deatha11, player_diea11 ] {PlayerDead();};
|
||||
|
||||
void() player_dieb1 = [ $deathb1, player_dieb2 ] {};
|
||||
void() player_dieb2 = [ $deathb2, player_dieb3 ] {};
|
||||
void() player_dieb3 = [ $deathb3, player_dieb4 ] {};
|
||||
void() player_dieb4 = [ $deathb4, player_dieb5 ] {};
|
||||
void() player_dieb5 = [ $deathb5, player_dieb6 ] {};
|
||||
void() player_dieb6 = [ $deathb6, player_dieb7 ] {};
|
||||
void() player_dieb7 = [ $deathb7, player_dieb8 ] {};
|
||||
void() player_dieb8 = [ $deathb8, player_dieb9 ] {};
|
||||
void() player_dieb9 = [ $deathb9, player_dieb9 ] {PlayerDead();};
|
||||
|
||||
void() player_diec1 = [ $deathc1, player_diec2 ] {};
|
||||
void() player_diec2 = [ $deathc2, player_diec3 ] {};
|
||||
void() player_diec3 = [ $deathc3, player_diec4 ] {};
|
||||
void() player_diec4 = [ $deathc4, player_diec5 ] {};
|
||||
void() player_diec5 = [ $deathc5, player_diec6 ] {};
|
||||
void() player_diec6 = [ $deathc6, player_diec7 ] {};
|
||||
void() player_diec7 = [ $deathc7, player_diec8 ] {};
|
||||
void() player_diec8 = [ $deathc8, player_diec9 ] {};
|
||||
void() player_diec9 = [ $deathc9, player_diec10 ] {};
|
||||
void() player_diec10 = [ $deathc10, player_diec11 ] {};
|
||||
void() player_diec11 = [ $deathc11, player_diec12 ] {};
|
||||
void() player_diec12 = [ $deathc12, player_diec13 ] {};
|
||||
void() player_diec13 = [ $deathc13, player_diec14 ] {};
|
||||
void() player_diec14 = [ $deathc14, player_diec15 ] {};
|
||||
void() player_diec15 = [ $deathc15, player_diec15 ] {PlayerDead();};
|
||||
|
||||
void() player_died1 = [ $deathd1, player_died2 ] {};
|
||||
void() player_died2 = [ $deathd2, player_died3 ] {};
|
||||
void() player_died3 = [ $deathd3, player_died4 ] {};
|
||||
void() player_died4 = [ $deathd4, player_died5 ] {};
|
||||
void() player_died5 = [ $deathd5, player_died6 ] {};
|
||||
void() player_died6 = [ $deathd6, player_died7 ] {};
|
||||
void() player_died7 = [ $deathd7, player_died8 ] {};
|
||||
void() player_died8 = [ $deathd8, player_died9 ] {};
|
||||
void() player_died9 = [ $deathd9, player_died9 ] {PlayerDead();};
|
||||
|
||||
void() player_diee1 = [ $deathe1, player_diee2 ] {};
|
||||
void() player_diee2 = [ $deathe2, player_diee3 ] {};
|
||||
void() player_diee3 = [ $deathe3, player_diee4 ] {};
|
||||
void() player_diee4 = [ $deathe4, player_diee5 ] {};
|
||||
void() player_diee5 = [ $deathe5, player_diee6 ] {};
|
||||
void() player_diee6 = [ $deathe6, player_diee7 ] {};
|
||||
void() player_diee7 = [ $deathe7, player_diee8 ] {};
|
||||
void() player_diee8 = [ $deathe8, player_diee9 ] {};
|
||||
void() player_diee9 = [ $deathe9, player_diee9 ] {PlayerDead();};
|
||||
|
||||
void() player_die_ax1 = [ $axdeth1, player_die_ax2 ] {};
|
||||
void() player_die_ax2 = [ $axdeth2, player_die_ax3 ] {};
|
||||
void() player_die_ax3 = [ $axdeth3, player_die_ax4 ] {};
|
||||
void() player_die_ax4 = [ $axdeth4, player_die_ax5 ] {};
|
||||
void() player_die_ax5 = [ $axdeth5, player_die_ax6 ] {};
|
||||
void() player_die_ax6 = [ $axdeth6, player_die_ax7 ] {};
|
||||
void() player_die_ax7 = [ $axdeth7, player_die_ax8 ] {};
|
||||
void() player_die_ax8 = [ $axdeth8, player_die_ax9 ] {};
|
||||
void() player_die_ax9 = [ $axdeth9, player_die_ax9 ] {PlayerDead();};
|
||||
|
||||
/*==========
|
||||
PlayerDie
|
||||
==========*/
|
||||
void(entity inflictor, entity attacker) PlayerDie =
|
||||
{
|
||||
// remove any powerups
|
||||
self.effects = 0;
|
||||
self.items = self.items - (self.items &
|
||||
(IT_SUPERHEALTH | IT_INVISIBILITY | IT_INVULNERABILITY | IT_SUIT | IT_QUAD) );
|
||||
self.modelindex = modelindex_player;
|
||||
|
||||
if (deathmatch || coop)
|
||||
DropBackpack();
|
||||
|
||||
self.weaponmodel = "";
|
||||
|
||||
// check for gib
|
||||
if (self.health < -40)
|
||||
{
|
||||
SpawnGib("progs/gib1.mdl");
|
||||
SpawnGib("progs/gib2.mdl");
|
||||
SpawnGib("progs/gib3.mdl");
|
||||
SpawnGib("progs/gib4.mdl");
|
||||
SpawnGib("progs/gib5.mdl");
|
||||
SpawnGib("progs/blood.mdl");
|
||||
SpawnGib("progs/blood.mdl");
|
||||
BecomeGibs();
|
||||
return;
|
||||
}
|
||||
|
||||
// remove any pitch and roll and set eye position
|
||||
self.angles_x = 0;
|
||||
self.angles_z = 0;
|
||||
self.view_ofs = '0 0 -8';
|
||||
|
||||
self.deadflag = DEAD_DYING;
|
||||
self.solid = SOLID_NOT;
|
||||
self.movetype = MOVETYPE_TOSS;
|
||||
|
||||
// give a dying player an upward push
|
||||
self.flags = self.flags - (self.flags & FL_ONGROUND);
|
||||
if (self.velocity_z < 10)
|
||||
self.velocity_z = self.velocity_z + random()*300;
|
||||
|
||||
// choose death animation
|
||||
PlayerDeathSound();
|
||||
if (self.weapon == IT_AXE)
|
||||
{
|
||||
player_die_ax1 ();
|
||||
return;
|
||||
}
|
||||
float i = randomrange(5);
|
||||
if (i == 0)
|
||||
player_diea1();
|
||||
else if (i == 1)
|
||||
player_dieb1();
|
||||
else if (i == 2)
|
||||
player_diec1();
|
||||
else if (i == 3)
|
||||
player_died1();
|
||||
else
|
||||
player_diee1();
|
||||
};
|
||||
78
mod_slipgate/source/server/progs.src
Normal file
78
mod_slipgate/source/server/progs.src
Normal file
@@ -0,0 +1,78 @@
|
||||
../../progs.dat
|
||||
#pragma optimise 1
|
||||
#pragma optimise strip_unused_fields
|
||||
#copyright Michael Coburn (c0burn) - michael.s.coburn@gmail.com
|
||||
|
||||
defs.qc
|
||||
subs.qc
|
||||
util.qc
|
||||
targets.qc
|
||||
tempents.qc
|
||||
|
||||
obituary.qc
|
||||
damage.qc
|
||||
|
||||
gore.qc
|
||||
projectiles.qc
|
||||
w_shotguns.qc
|
||||
weapons.qc
|
||||
|
||||
waypoints.qc
|
||||
monsters.qc
|
||||
fight.qc
|
||||
ai.qc
|
||||
|
||||
|
||||
|
||||
items.qc
|
||||
it_ammo.qc
|
||||
it_armor.qc
|
||||
it_backpack.qc
|
||||
it_health.qc
|
||||
it_keys.qc
|
||||
it_powerups.qc
|
||||
it_weapons.qc
|
||||
|
||||
ambient.qc
|
||||
bodyque.qc
|
||||
bmodel.qc
|
||||
breakable.qc
|
||||
bubbles.qc
|
||||
buttons.qc
|
||||
doors.qc
|
||||
info.qc
|
||||
lights.qc
|
||||
misc.qc
|
||||
plats.qc
|
||||
trains.qc
|
||||
trap_explobox.qc
|
||||
trap_fireball.qc
|
||||
trap_shooter.qc
|
||||
triggers.qc
|
||||
trigger_changelevel.qc
|
||||
trigger_hurt.qc
|
||||
trigger_ladder.qc
|
||||
trigger_monsterjump.qc
|
||||
trigger_push.qc
|
||||
trigger_teleport.qc
|
||||
world.qc
|
||||
|
||||
intermission.qc
|
||||
client.qc
|
||||
player.qc
|
||||
|
||||
monsters/ogre.qc
|
||||
monsters/demon.qc
|
||||
monsters/shambler.qc
|
||||
monsters/knight.qc
|
||||
monsters/soldier.qc
|
||||
monsters/wizard.qc
|
||||
monsters/dog.qc
|
||||
monsters/zombie.qc
|
||||
monsters/boss.qc
|
||||
monsters/tarbaby.qc
|
||||
monsters/hknight.qc
|
||||
monsters/fish.qc
|
||||
monsters/shalrath.qc
|
||||
monsters/enforcer.qc
|
||||
monsters/oldone.qc
|
||||
144
mod_slipgate/source/server/projectiles.qc
Normal file
144
mod_slipgate/source/server/projectiles.qc
Normal file
@@ -0,0 +1,144 @@
|
||||
void() s_explode1 = [0, s_explode2] {};
|
||||
void() s_explode2 = [1, s_explode3] {};
|
||||
void() s_explode3 = [2, s_explode4] {};
|
||||
void() s_explode4 = [3, s_explode5] {};
|
||||
void() s_explode5 = [4, s_explode6] {};
|
||||
void() s_explode6 = [5, SUB_Remove] {};
|
||||
|
||||
/*==========
|
||||
BecomeExplosion
|
||||
==========*/
|
||||
void() BecomeExplosion =
|
||||
{
|
||||
self.solid = SOLID_NOT;
|
||||
self.movetype = MOVETYPE_NONE;
|
||||
self.velocity = '0 0 0';
|
||||
self.touch = SUB_Null;
|
||||
setmodel (self, "progs/s_explod.spr");
|
||||
s_explode1();
|
||||
};
|
||||
|
||||
/*==========
|
||||
grenade_explode
|
||||
==========*/
|
||||
static void() grenade_explode =
|
||||
{
|
||||
RadiusDamage (self, self.owner, self.dmg, world);
|
||||
te_explosion(self.origin);
|
||||
BecomeExplosion();
|
||||
};
|
||||
|
||||
/*==========
|
||||
grenade_touch
|
||||
==========*/
|
||||
static void() grenade_touch =
|
||||
{
|
||||
if (pointcontents(self.origin) == CONTENT_SKY)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
if (other.takedamage == DAMAGE_AIM)
|
||||
{
|
||||
grenade_explode();
|
||||
return;
|
||||
}
|
||||
sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
|
||||
};
|
||||
|
||||
/*==========
|
||||
launch_grenade
|
||||
|
||||
used for player, zombie and ogre grenades
|
||||
==========*/
|
||||
void(vector org, vector dir, float spd, float dam) launch_grenade =
|
||||
{
|
||||
newmis = spawn();
|
||||
newmis.classname = "grenade";
|
||||
newmis.owner = self;
|
||||
newmis.solid = SOLID_BBOX;
|
||||
newmis.movetype = MOVETYPE_BOUNCE;
|
||||
|
||||
setmodel (newmis, "progs/grenade.mdl");
|
||||
setsize (newmis, '0 0 0', '0 0 0');
|
||||
setorigin (newmis, org);
|
||||
|
||||
newmis.dmg = dam;
|
||||
|
||||
newmis.touch = grenade_touch;
|
||||
newmis.angles = vectoangles(dir);
|
||||
newmis.velocity = dir * spd;
|
||||
|
||||
newmis.think = grenade_explode;
|
||||
newmis.nextthink = time + 2.5;
|
||||
};
|
||||
|
||||
/*==========
|
||||
spike_touch
|
||||
==========*/
|
||||
static void() spike_touch2 =
|
||||
{
|
||||
if (pointcontents(self.origin) == CONTENT_SKY)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
|
||||
// move out of the wall / floor slightly
|
||||
self.origin = self.origin - 8*normalize(self.velocity);
|
||||
|
||||
// lasers always play an impact sound
|
||||
if (self.classname == "laser")
|
||||
sound (self, CHAN_WEAPON, "enforcer/enfstop.wav", 1, ATTN_IDLE);
|
||||
|
||||
if (other.takedamage)
|
||||
{
|
||||
Damage(other, self, self.owner, self.dmg);
|
||||
if (other.solid == SOLID_BSP)
|
||||
SpawnTouchParticles(self.dmg, 192);
|
||||
else
|
||||
SpawnTouchblood(self.dmg);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self.classname == "laser")
|
||||
te_gunshot(self.origin);
|
||||
else if (self.classname == "spike")
|
||||
te_spike(self.origin);
|
||||
else if (self.classname == "superspike")
|
||||
te_superspike(self.origin);
|
||||
else if (self.classname == "wizspike")
|
||||
te_wizspike(self.origin);
|
||||
else if (self.classname == "knightspike")
|
||||
te_knightspike(self.origin);
|
||||
}
|
||||
|
||||
remove(self);
|
||||
};
|
||||
|
||||
/*==========
|
||||
launch_spike
|
||||
|
||||
used for nails, lasers, scrag spit and hellknight fire
|
||||
==========*/
|
||||
void(string name, string mod, vector org, vector dir, float spd, float dam) launch_spike2 =
|
||||
{
|
||||
newmis = spawn();
|
||||
newmis.classname = name; // spike, superspike, laser, knightspike, wizspike
|
||||
newmis.owner = self;
|
||||
newmis.solid = SOLID_BBOX;
|
||||
newmis.movetype = MOVETYPE_FLYMISSILE;
|
||||
|
||||
setmodel (newmis, mod);
|
||||
setsize (newmis, '0 0 0', '0 0 0');
|
||||
setorigin (newmis, org);
|
||||
|
||||
newmis.dmg = dam;
|
||||
|
||||
newmis.touch = spike_touch2;
|
||||
newmis.angles = vectoangles(dir);
|
||||
newmis.velocity = dir * spd;
|
||||
|
||||
newmis.think = SUB_Remove;
|
||||
newmis.nextthink = time + 10;
|
||||
};
|
||||
119
mod_slipgate/source/server/subs.qc
Normal file
119
mod_slipgate/source/server/subs.qc
Normal file
@@ -0,0 +1,119 @@
|
||||
/*==========
|
||||
SUB_PainNull
|
||||
==========*/
|
||||
void(entity attacker, float damage) SUB_PainNull = {};
|
||||
|
||||
/*==========
|
||||
SUB_Null
|
||||
==========*/
|
||||
void() SUB_Null = {};
|
||||
|
||||
/*==========
|
||||
SUB_Remove
|
||||
==========*/
|
||||
void() SUB_Remove = {remove(self);};
|
||||
|
||||
/*==========
|
||||
SUB_Fade
|
||||
==========*/
|
||||
void() SUB_Fade =
|
||||
{
|
||||
if (self.alpha == 0)
|
||||
self.alpha = 1;
|
||||
self.alpha = self.alpha - 0.1;
|
||||
if (self.alpha <= 0)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
self.think = SUB_Fade;
|
||||
self.nextthink = time + 0.1;
|
||||
};
|
||||
|
||||
/*==========
|
||||
SetMoveDir
|
||||
|
||||
the angle field in map editors is a single float, so up and down are constant values
|
||||
==========*/
|
||||
void() SetMovedir =
|
||||
{
|
||||
if (self.angles == '0 -1 0') // up
|
||||
self.movedir = '0 0 1';
|
||||
else if (self.angles == '0 -2 0') // down
|
||||
self.movedir = '0 0 -1';
|
||||
else
|
||||
{
|
||||
makevectors (self.angles);
|
||||
self.movedir = v_forward;
|
||||
}
|
||||
self.angles = '0 0 0';
|
||||
};
|
||||
|
||||
/*==========
|
||||
SUB_CalcMoveDone
|
||||
|
||||
After moving, set origin to exact final destination and run think1
|
||||
==========*/
|
||||
void() SUB_CalcMoveDone =
|
||||
{
|
||||
setorigin(self, self.finaldest);
|
||||
self.velocity = '0 0 0';
|
||||
self.think = SUB_Null;
|
||||
self.nextthink = -1;
|
||||
if (self.think1)
|
||||
self.think1();
|
||||
};
|
||||
|
||||
/*==========
|
||||
SUB_CalcMove
|
||||
|
||||
calculate self.velocity and self.nextthink to reach dest from
|
||||
self.origin traveling at speed
|
||||
==========*/
|
||||
void(vector dst, float spd, void() thnk) SUB_CalcMove =
|
||||
{
|
||||
if (!spd)
|
||||
{
|
||||
objerror("SUB_CalcMove: no speed defined");
|
||||
return;
|
||||
}
|
||||
|
||||
self.think = SUB_CalcMoveDone;
|
||||
self.think1 = thnk;
|
||||
self.finaldest = dst;
|
||||
|
||||
if (dst == self.origin)
|
||||
{
|
||||
self.velocity = '0 0 0';
|
||||
if (self.movetype == MOVETYPE_PUSH)
|
||||
self.nextthink = self.ltime + 0.01;
|
||||
else
|
||||
self.nextthink = time + 0.01;
|
||||
return;
|
||||
}
|
||||
|
||||
vector delta = dst - self.origin;
|
||||
float traveltime = vlen(delta) / spd;
|
||||
if (traveltime < 0.01)
|
||||
{
|
||||
self.velocity = '0 0 0';
|
||||
if (self.movetype == MOVETYPE_PUSH)
|
||||
self.nextthink = self.ltime + 0.01;
|
||||
else
|
||||
self.nextthink = time + 0.01;
|
||||
return;
|
||||
}
|
||||
|
||||
self.velocity = delta / traveltime;
|
||||
if (self.movetype == MOVETYPE_PUSH)
|
||||
self.nextthink = self.ltime + traveltime;
|
||||
else
|
||||
self.nextthink = time + traveltime;
|
||||
};
|
||||
|
||||
void(float normal) SUB_AttackFinished =
|
||||
{
|
||||
self.cnt = 0; // refire count for nightmare
|
||||
if (skill != 3)
|
||||
self.attack_finished = time + normal;
|
||||
};
|
||||
130
mod_slipgate/source/server/targets.qc
Normal file
130
mod_slipgate/source/server/targets.qc
Normal file
@@ -0,0 +1,130 @@
|
||||
void() UseTargets;
|
||||
|
||||
/*==========
|
||||
DelayUseTargets
|
||||
|
||||
use targets after a delay
|
||||
==========*/
|
||||
void() DelayUseTargets =
|
||||
{
|
||||
activator = self.enemy;
|
||||
UseTargets();
|
||||
remove(self); // temporary entity
|
||||
};
|
||||
|
||||
/*==========
|
||||
DelayKillTargets
|
||||
|
||||
actually removes any kiltargets
|
||||
==========*/
|
||||
void() DelayKillTargets =
|
||||
{
|
||||
entity e = world;
|
||||
while (1)
|
||||
{
|
||||
e = find(e, targetname, self.killtarget);
|
||||
if (!e)
|
||||
break;
|
||||
remove(e);
|
||||
}
|
||||
remove(self); // temporary entity
|
||||
};
|
||||
|
||||
/*==========
|
||||
UseTargets
|
||||
|
||||
"activator" should be set to the entity that initiated the firing
|
||||
|
||||
Centerprints any "message" to the "activator"
|
||||
|
||||
Removes all entities with a "targetname" that matches "killtarget"
|
||||
|
||||
Finds all entities with a "targetname" that matches "target" and calls their "use" function
|
||||
|
||||
If "delay" is set, a temporary entity will be created that will only fire the targets after the delay
|
||||
==========*/
|
||||
void() UseTargets =
|
||||
{
|
||||
entity e, act;
|
||||
|
||||
// if delay is set, create a temporary entity to fire later
|
||||
if (self.delay > 0)
|
||||
{
|
||||
e = spawn();
|
||||
e.classname = "DelayUseTargets";
|
||||
e.enemy = activator;
|
||||
e.message = self.message;
|
||||
e.target = self.target;
|
||||
e.killtarget = self.killtarget;
|
||||
e.think = DelayUseTargets;
|
||||
e.nextthink = time + self.delay;
|
||||
return;
|
||||
}
|
||||
|
||||
// print any message if the activator is a player
|
||||
if (activator.classname == "player" && self.message != "")
|
||||
{
|
||||
centerprint (activator, self.message);
|
||||
if (!self.noise)
|
||||
sound (activator, CHAN_VOICE, "misc/talk.wav", 1, ATTN_NORM);
|
||||
}
|
||||
|
||||
// remove any killtargets. we now support setting both target and killtarget on entities.
|
||||
if (self.killtarget != "")
|
||||
{
|
||||
// we use a think to remove the killtargets because we could be in the
|
||||
// middle of a touch function, which can cause crashes in vanilla engines
|
||||
// without fixed SV_TouchLinks
|
||||
e = spawn();
|
||||
e.classname = "DelayKillTargets";
|
||||
e.killtarget = self.killtarget;
|
||||
e.think = DelayKillTargets;
|
||||
e.nextthink = time; // do it on the next frame
|
||||
|
||||
// clear out some essential fields to stop it being used before the actual removal
|
||||
e = world;
|
||||
while (1)
|
||||
{
|
||||
e = find(e, targetname, self.killtarget);
|
||||
if (!e)
|
||||
break;
|
||||
e.use = SUB_Null;
|
||||
e.touch = SUB_Null;
|
||||
e.think = SUB_Null;
|
||||
e.nextthink = -1;
|
||||
}
|
||||
|
||||
// workaround for various maps that have triggers which contains both "target" and "killtarget"
|
||||
// set to identical values
|
||||
if (self.target == self.killtarget)
|
||||
return;
|
||||
}
|
||||
|
||||
// fire any targets
|
||||
if (self.target != "")
|
||||
{
|
||||
act = activator;
|
||||
e = world;
|
||||
while (1)
|
||||
{
|
||||
e = find (e, targetname, self.target);
|
||||
if (!e)
|
||||
break;
|
||||
|
||||
// save globals
|
||||
// set self to the entity being triggered and other to the activator
|
||||
entity stemp = self;
|
||||
entity otemp = other;
|
||||
self = e;
|
||||
other = stemp;
|
||||
|
||||
if (self.use)
|
||||
self.use();
|
||||
|
||||
// restore globals
|
||||
self = stemp;
|
||||
other = otemp;
|
||||
activator = act;
|
||||
}
|
||||
}
|
||||
};
|
||||
185
mod_slipgate/source/server/tempents.qc
Normal file
185
mod_slipgate/source/server/tempents.qc
Normal file
@@ -0,0 +1,185 @@
|
||||
/*==========
|
||||
te_teleport
|
||||
==========*/
|
||||
void(vector org) te_teleport =
|
||||
{
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_TELEPORT);
|
||||
WriteCoord (MSG_BROADCAST, org_x);
|
||||
WriteCoord (MSG_BROADCAST, org_y);
|
||||
WriteCoord (MSG_BROADCAST, org_z);
|
||||
};
|
||||
|
||||
/*==========
|
||||
te_teleport
|
||||
==========*/
|
||||
void(vector org) te_explosion =
|
||||
{
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_EXPLOSION);
|
||||
WriteCoord (MSG_BROADCAST, org_x);
|
||||
WriteCoord (MSG_BROADCAST, org_y);
|
||||
WriteCoord (MSG_BROADCAST, org_z);
|
||||
};
|
||||
|
||||
/*==========
|
||||
te_explosion2
|
||||
==========*/
|
||||
void(vector org, float col, float len) te_explosion2 =
|
||||
{
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_EXPLOSION2);
|
||||
WriteCoord (MSG_BROADCAST, org_x);
|
||||
WriteCoord (MSG_BROADCAST, org_y);
|
||||
WriteCoord (MSG_BROADCAST, org_z);
|
||||
WriteByte (MSG_BROADCAST, col);
|
||||
WriteByte (MSG_BROADCAST, len);
|
||||
};
|
||||
|
||||
/*==========
|
||||
te_tarexplosion
|
||||
==========*/
|
||||
void(vector org) te_tarexplosion =
|
||||
{
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_TAREXPLOSION);
|
||||
WriteCoord (MSG_BROADCAST, org_x);
|
||||
WriteCoord (MSG_BROADCAST, org_y);
|
||||
WriteCoord (MSG_BROADCAST, org_z);
|
||||
};
|
||||
|
||||
/*==========
|
||||
te_gunshot
|
||||
==========*/
|
||||
void(vector org) te_gunshot =
|
||||
{
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_GUNSHOT);
|
||||
WriteCoord (MSG_BROADCAST, org_x);
|
||||
WriteCoord (MSG_BROADCAST, org_y);
|
||||
WriteCoord (MSG_BROADCAST, org_z);
|
||||
};
|
||||
|
||||
/*==========
|
||||
te_spike
|
||||
==========*/
|
||||
void(vector org) te_spike =
|
||||
{
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_SPIKE);
|
||||
WriteCoord (MSG_BROADCAST, org_x);
|
||||
WriteCoord (MSG_BROADCAST, org_y);
|
||||
WriteCoord (MSG_BROADCAST, org_z);
|
||||
};
|
||||
|
||||
/*==========
|
||||
te_superspike
|
||||
==========*/
|
||||
void(vector org) te_superspike =
|
||||
{
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
|
||||
WriteCoord (MSG_BROADCAST, org_x);
|
||||
WriteCoord (MSG_BROADCAST, org_y);
|
||||
WriteCoord (MSG_BROADCAST, org_z);
|
||||
};
|
||||
|
||||
/*==========
|
||||
te_wizspike
|
||||
==========*/
|
||||
void(vector org) te_wizspike =
|
||||
{
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
|
||||
WriteCoord (MSG_BROADCAST, org_x);
|
||||
WriteCoord (MSG_BROADCAST, org_y);
|
||||
WriteCoord (MSG_BROADCAST, org_z);
|
||||
};
|
||||
|
||||
/*==========
|
||||
te_knightspike
|
||||
==========*/
|
||||
void(vector org) te_knightspike =
|
||||
{
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_KNIGHTSPIKE);
|
||||
WriteCoord (MSG_BROADCAST, org_x);
|
||||
WriteCoord (MSG_BROADCAST, org_y);
|
||||
WriteCoord (MSG_BROADCAST, org_z);
|
||||
};
|
||||
|
||||
/*==========
|
||||
te_lightning1
|
||||
==========*/
|
||||
void(vector v1, vector v2, entity ent) te_lightning1 =
|
||||
{
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_LIGHTNING1);
|
||||
WriteEntity (MSG_BROADCAST, ent);
|
||||
WriteCoord (MSG_BROADCAST, v1_x);
|
||||
WriteCoord (MSG_BROADCAST, v1_y);
|
||||
WriteCoord (MSG_BROADCAST, v1_z);
|
||||
WriteCoord (MSG_BROADCAST, v2_x);
|
||||
WriteCoord (MSG_BROADCAST, v2_y);
|
||||
WriteCoord (MSG_BROADCAST, v2_z);
|
||||
};
|
||||
|
||||
/*==========
|
||||
te_lightning2
|
||||
==========*/
|
||||
void(vector v1, vector v2, entity ent) te_lightning2 =
|
||||
{
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
|
||||
WriteEntity (MSG_BROADCAST, ent);
|
||||
WriteCoord (MSG_BROADCAST, v1_x);
|
||||
WriteCoord (MSG_BROADCAST, v1_y);
|
||||
WriteCoord (MSG_BROADCAST, v1_z);
|
||||
WriteCoord (MSG_BROADCAST, v2_x);
|
||||
WriteCoord (MSG_BROADCAST, v2_y);
|
||||
WriteCoord (MSG_BROADCAST, v2_z);
|
||||
};
|
||||
|
||||
/*==========
|
||||
te_lightning3
|
||||
==========*/
|
||||
void(vector v1, vector v2, entity ent) te_lightning3 =
|
||||
{
|
||||
WriteByte (MSG_ALL, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_ALL, TE_LIGHTNING3);
|
||||
WriteEntity (MSG_ALL, ent);
|
||||
WriteCoord (MSG_ALL, v1_x);
|
||||
WriteCoord (MSG_ALL, v1_y);
|
||||
WriteCoord (MSG_ALL, v1_z);
|
||||
WriteCoord (MSG_ALL, v2_x);
|
||||
WriteCoord (MSG_ALL, v2_y);
|
||||
WriteCoord (MSG_ALL, v2_z);
|
||||
};
|
||||
|
||||
/*==========
|
||||
te_beam
|
||||
==========*/
|
||||
void(vector v1, vector v2, entity ent) te_beam =
|
||||
{
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_BEAM);
|
||||
WriteEntity (MSG_BROADCAST, ent);
|
||||
WriteCoord (MSG_BROADCAST, v1_x);
|
||||
WriteCoord (MSG_BROADCAST, v1_y);
|
||||
WriteCoord (MSG_BROADCAST, v1_z);
|
||||
WriteCoord (MSG_BROADCAST, v2_x);
|
||||
WriteCoord (MSG_BROADCAST, v2_y);
|
||||
WriteCoord (MSG_BROADCAST, v2_z);
|
||||
};
|
||||
|
||||
/*==========
|
||||
te_lavasplash
|
||||
==========*/
|
||||
void(vector org) te_lavasplash =
|
||||
{
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_LAVASPLASH);
|
||||
WriteCoord (MSG_BROADCAST, org_x);
|
||||
WriteCoord (MSG_BROADCAST, org_y);
|
||||
WriteCoord (MSG_BROADCAST, org_z);
|
||||
};
|
||||
159
mod_slipgate/source/server/trains.qc
Normal file
159
mod_slipgate/source/server/trains.qc
Normal file
@@ -0,0 +1,159 @@
|
||||
void() train_next;
|
||||
|
||||
void() train_blocked =
|
||||
{
|
||||
if (time < self.attack_finished)
|
||||
return;
|
||||
self.attack_finished = time + 0.5;
|
||||
Damage (other, self, self, self.dmg);
|
||||
};
|
||||
|
||||
void() train_wait =
|
||||
{
|
||||
self.think = train_next;
|
||||
if (self.wait > 0)
|
||||
{
|
||||
if (self.movetype == MOVETYPE_PUSH)
|
||||
self.nextthink = self.ltime + self.wait;
|
||||
else
|
||||
self.nextthink = time + self.wait;
|
||||
|
||||
if (self.noise != "")
|
||||
sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self.movetype == MOVETYPE_PUSH)
|
||||
self.nextthink = self.ltime + 0.1;
|
||||
else
|
||||
self.nextthink = time + 0.1;
|
||||
}
|
||||
};
|
||||
|
||||
void() train_next =
|
||||
{
|
||||
entity targ = find(world, targetname, self.target);
|
||||
self.target = targ.target;
|
||||
if (!self.target)
|
||||
{
|
||||
self.velocity = '0 0 0';
|
||||
self.think = SUB_Null;
|
||||
self.nextthink = -1;
|
||||
objerror("train_next: no next target");
|
||||
return;
|
||||
}
|
||||
|
||||
if (targ.wait > 0)
|
||||
self.wait = targ.wait;
|
||||
else
|
||||
self.wait = 0;
|
||||
|
||||
if (self.noise1 != "")
|
||||
sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
|
||||
SUB_CalcMove (targ.origin - self.mins, self.speed, train_wait);
|
||||
};
|
||||
|
||||
void() train_use =
|
||||
{
|
||||
self.use = SUB_Null;
|
||||
train_next();
|
||||
};
|
||||
|
||||
void() train_find =
|
||||
{
|
||||
entity targ = find(world, targetname, self.target);
|
||||
self.target = targ.target;
|
||||
setorigin (self, targ.origin - self.mins);
|
||||
if (!self.targetname)
|
||||
{
|
||||
if (self.movetype == MOVETYPE_PUSH)
|
||||
self.nextthink = self.ltime + 0.1;
|
||||
else
|
||||
self.nextthink = time + 0.1;
|
||||
self.think = train_next;
|
||||
}
|
||||
else
|
||||
self.use = train_use;
|
||||
};
|
||||
|
||||
/*QUAKED func_train (0 .5 .8) ?
|
||||
Trains are moving platforms that players can ride.
|
||||
Must target a series of 'path_corner' entities.
|
||||
The targets origin specifies the min point of the train at each corner.
|
||||
It will always position itself on its first target at map load.
|
||||
If a targetname is set, it must be triggered to start moving, otherwise it will start immediately.
|
||||
|
||||
speed default 100
|
||||
dmg default 2
|
||||
sounds
|
||||
-1) custom, set "noise" and "noise1"
|
||||
0) none
|
||||
1) ratchet metal
|
||||
*/
|
||||
void() func_train =
|
||||
{
|
||||
if (!self.target)
|
||||
{
|
||||
objerror ("func_train without a target");
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
|
||||
self.solid = SOLID_BSP;
|
||||
self.movetype = MOVETYPE_PUSH;
|
||||
self.blocked = train_blocked;
|
||||
setmodel (self, self.model);
|
||||
setsize (self, self.mins, self.maxs);
|
||||
setorigin (self, self.origin);
|
||||
|
||||
SetPositiveDefault(speed, 100);
|
||||
SetPositiveDefault(dmg, 2);
|
||||
if (self.sounds == 0)
|
||||
{
|
||||
self.noise = "";
|
||||
self.noise1 = "";
|
||||
}
|
||||
else if (self.sounds == 1)
|
||||
{
|
||||
self.noise = "plats/train2.wav";
|
||||
self.noise1 = "plats/train1.wav";
|
||||
}
|
||||
if (self.noise != "")
|
||||
precache_sound (self.noise);
|
||||
if (self.noise1 != "")
|
||||
precache_sound (self.noise1);
|
||||
|
||||
self.think = train_find;
|
||||
self.nextthink = self.ltime + 0.1;
|
||||
};
|
||||
|
||||
/*QUAKED misc_teleporttrain (.5 .5 .5) (-16 -16 -16) (16 16 16) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{ model("progs/teleport.mdl"); }
|
||||
|
||||
Floating teleporter target for final boss level. Must target a series of 'path_corner' entities.
|
||||
It will always position itself on its first target at map load.
|
||||
If a targetname is set, it must be triggered to start moving, otherwise it will start immediately.
|
||||
|
||||
speed default 100
|
||||
*/
|
||||
void() misc_teleporttrain =
|
||||
{
|
||||
if (!self.target)
|
||||
{
|
||||
objerror ("misc_teleporttrain without a target");
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
|
||||
self.solid = SOLID_NOT;
|
||||
self.movetype = MOVETYPE_NOCLIP;
|
||||
precache_model ("progs/teleport.mdl");
|
||||
setmodel (self, "progs/teleport.mdl");
|
||||
setsize (self, '-16 -16 -16', '16 16 16');
|
||||
|
||||
SetPositiveDefault(speed, 100);
|
||||
self.avelocity = '20 40 80';
|
||||
|
||||
self.think = train_find;
|
||||
self.nextthink = time + 0.1;
|
||||
};
|
||||
143
mod_slipgate/source/server/trap_explobox.qc
Normal file
143
mod_slipgate/source/server/trap_explobox.qc
Normal file
@@ -0,0 +1,143 @@
|
||||
/*==========
|
||||
explobox_explode
|
||||
==========*/
|
||||
static void() explobox_explode =
|
||||
{
|
||||
setorigin(self, realorigin(self)); // fix our origin as we're a bmodel
|
||||
|
||||
RadiusDamage (self, self, self.dmg, world);
|
||||
te_explosion(self.origin);
|
||||
BecomeExplosion();
|
||||
|
||||
// fire targets
|
||||
activator = self.enemy;
|
||||
UseTargets();
|
||||
};
|
||||
|
||||
/*==========
|
||||
explobox_die
|
||||
==========*/
|
||||
static void(entity inflictor, entity attacker) explobox_die =
|
||||
{
|
||||
self.enemy = attacker; // for firing targets
|
||||
self.solid = SOLID_NOT;
|
||||
self.takedamage = DAMAGE_NO;
|
||||
self.think = explobox_explode;
|
||||
self.nextthink = self.ltime + 0.1;
|
||||
};
|
||||
|
||||
/*==========
|
||||
explobox_use
|
||||
==========*/
|
||||
static static void() explobox_use =
|
||||
{
|
||||
self.enemy = activator; // for firing targets
|
||||
self.use = SUB_Null;
|
||||
self.think = explobox_explode;
|
||||
self.nextthink = self.ltime + 0.1;
|
||||
};
|
||||
|
||||
/*==========
|
||||
explobox_drop
|
||||
==========*/
|
||||
static float() explobox_drop =
|
||||
{
|
||||
self.origin_z = self.origin_z + 2;
|
||||
if (!droptofloor())
|
||||
{
|
||||
dprint (self.classname);
|
||||
dprint (" fell out of level at ");
|
||||
dprint (vtos(realorigin(self)));
|
||||
dprint ("\n");
|
||||
remove(self);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
/*==========
|
||||
explobox_start
|
||||
==========*/
|
||||
static void() explobox_start =
|
||||
{
|
||||
self.solid = SOLID_BSP;
|
||||
self.movetype = MOVETYPE_PUSH;
|
||||
if (self.classname == "misc_explobox2")
|
||||
{
|
||||
precache_model2 ("maps/b_exbox2.bsp");
|
||||
setmodel (self, "maps/b_exbox2.bsp");
|
||||
setsize(self, '0 0 0', '32 32 32');
|
||||
if (explobox_drop())
|
||||
return;
|
||||
}
|
||||
else if (self.classname == "misc_explobox")
|
||||
{
|
||||
precache_model ("maps/b_explob.bsp");
|
||||
setmodel (self, "maps/b_explob.bsp");
|
||||
setsize(self, '0 0 0', '32 32 64');
|
||||
if (explobox_drop())
|
||||
return;
|
||||
}
|
||||
else
|
||||
setmodel (self, self.model);
|
||||
|
||||
self.classname = "explobox";
|
||||
SetPositiveDefault(dmg, 160);
|
||||
self.colour = 192;
|
||||
|
||||
// if targetname is set, it must be triggered
|
||||
if (self.targetname != "")
|
||||
self.use = explobox_use;
|
||||
else
|
||||
{
|
||||
SetPositiveDefault(health, 20);
|
||||
self.takedamage = DAMAGE_AIM;
|
||||
self.th_die = explobox_die;
|
||||
}
|
||||
};
|
||||
|
||||
/*QUAKED misc_explobox (1 .5 0) (0 0 0) (32 32 64) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model("maps/b_explob.bsp");
|
||||
}
|
||||
Large explosive box
|
||||
If "targetname" is set, cannot be shot and must be triggered.
|
||||
|
||||
Keys:
|
||||
"targetname" - if set, cannot be shot and must be triggered.
|
||||
"health" - override default health of 20.
|
||||
"dmg" - override default damage of 160.
|
||||
*/
|
||||
void() misc_explobox =
|
||||
{
|
||||
explobox_start();
|
||||
};
|
||||
|
||||
/*QUAKED misc_explobox2 (1 .5 0) (0 0 0) (32 32 32) X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{
|
||||
model("maps/b_exbox2.bsp");
|
||||
}
|
||||
Small explosive box
|
||||
|
||||
Keys:
|
||||
"targetname" - if set, cannot be shot and must be triggered.
|
||||
"health" - override default health of 20.
|
||||
"dmg" - override default damage of 160.
|
||||
*/
|
||||
void() misc_explobox2 =
|
||||
{
|
||||
explobox_start();
|
||||
};
|
||||
|
||||
/*QUAKED func_explosive (1 .5 0) ? X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
Brush that explodes when shot or triggered
|
||||
|
||||
Keys:
|
||||
"targetname" - if set, cannot be shot and must be triggered.
|
||||
"health" - override default health of 20.
|
||||
"dmg" - override default damage of 160.
|
||||
*/
|
||||
void() func_explosive =
|
||||
{
|
||||
explobox_start();
|
||||
};
|
||||
87
mod_slipgate/source/server/trap_fireball.qc
Normal file
87
mod_slipgate/source/server/trap_fireball.qc
Normal file
@@ -0,0 +1,87 @@
|
||||
static enumflags { LAVABALL_SOUNDS };
|
||||
|
||||
/*==========
|
||||
fireball_touch
|
||||
==========*/
|
||||
static void() fireball_touch =
|
||||
{
|
||||
if (other.classname == self.classname)
|
||||
return;
|
||||
|
||||
Damage (other, self, self, self.dmg);
|
||||
remove(self);
|
||||
};
|
||||
|
||||
/*==========
|
||||
fireball_launch
|
||||
==========*/
|
||||
static void() fireball_launch =
|
||||
{
|
||||
if (self.spawnflags & LAVABALL_SOUNDS)
|
||||
sound (self, CHAN_VOICE, "boss1/throw.wav", 1, ATTN_NORM);
|
||||
|
||||
for (float i = 0; i < self.count; i++)
|
||||
{
|
||||
entity fireball = spawn();
|
||||
fireball.classname = "fireball";
|
||||
fireball.solid = SOLID_TRIGGER;
|
||||
fireball.movetype = MOVETYPE_TOSS;
|
||||
setmodel (fireball, "progs/lavaball.mdl");
|
||||
setsize (fireball, '0 0 0', '0 0 0');
|
||||
setorigin (fireball, self.origin);
|
||||
|
||||
fireball.velocity_x = crandom() * 50;
|
||||
fireball.velocity_y = crandom() * 50;
|
||||
fireball.velocity_z = self.speed + (random() * 200);
|
||||
fireball.avelocity = [100, 100, 100];
|
||||
|
||||
fireball.touch = fireball_touch;
|
||||
fireball.think = SUB_Remove;
|
||||
fireball.nextthink = time + 5;
|
||||
}
|
||||
};
|
||||
|
||||
/*==========
|
||||
fireball_fly
|
||||
==========*/
|
||||
static void() fireball_fly =
|
||||
{
|
||||
fireball_launch();
|
||||
self.think = fireball_fly;
|
||||
self.nextthink = time + self.wait + random()*self.wait;
|
||||
};
|
||||
|
||||
/*QUAKED misc_fireball (1 .5 0) (-8 -8 -8) (8 8 8) SOUNDS X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
{ model ("progs/lavaball.mdl"); }
|
||||
Flying lava balls
|
||||
|
||||
Keys:
|
||||
speed - set the vertical speed of fireballs. default 1000.
|
||||
wait - delay between fireballs (with some randomness). default 3 seconds.
|
||||
count - number of fireballs to launch. default 1.
|
||||
dmg - damage dealt by fireballs. default 20.
|
||||
targetname - if set, must be triggered to activate.
|
||||
|
||||
Spawnflags:
|
||||
SOUNDS - if set, fireballs will make a whooshing sound when launched.
|
||||
*/
|
||||
void() misc_fireball =
|
||||
{
|
||||
precache_model ("progs/lavaball.mdl");
|
||||
if (self.spawnflags & LAVABALL_SOUNDS)
|
||||
precache_sound ("boss1/throw.wav");
|
||||
|
||||
SetPositiveDefault(speed, 1000);
|
||||
SetPositiveDefault(count, 1);
|
||||
SetPositiveDefault(wait, 3);
|
||||
SetPositiveDefault(dmg, 20);
|
||||
|
||||
// triggered only
|
||||
if (self.targetname != "")
|
||||
self.use = fireball_launch;
|
||||
else
|
||||
{
|
||||
self.think = fireball_fly;
|
||||
self.nextthink = time + self.wait + random()*self.wait;
|
||||
}
|
||||
};
|
||||
93
mod_slipgate/source/server/trap_shooter.qc
Normal file
93
mod_slipgate/source/server/trap_shooter.qc
Normal file
@@ -0,0 +1,93 @@
|
||||
static enumflags { SHOOTER_SUPERSPIKE, SHOOTER_LASER };
|
||||
|
||||
void(vector org, vector vec) LaunchLaser;
|
||||
|
||||
/*==========
|
||||
shooter_use
|
||||
==========*/
|
||||
static void() shooter_use =
|
||||
{
|
||||
if (self.spawnflags & SHOOTER_LASER)
|
||||
{
|
||||
sound (self, CHAN_VOICE, "enforcer/enfire.wav", 1, ATTN_NORM);
|
||||
LaunchLaser (self.origin, self.movedir);
|
||||
}
|
||||
else if (self.spawnflags & SHOOTER_SUPERSPIKE)
|
||||
{
|
||||
sound (self, CHAN_VOICE, "weapons/spike2.wav", 1, ATTN_NORM);
|
||||
launch_spike (self.origin, self.movedir);
|
||||
newmis.touch = superspike_touch;
|
||||
}
|
||||
else
|
||||
{
|
||||
sound (self, CHAN_VOICE, "weapons/rocket1i.wav", 1, ATTN_NORM);
|
||||
launch_spike (self.origin, self.movedir);
|
||||
}
|
||||
newmis.velocity = self.movedir * 500;
|
||||
};
|
||||
|
||||
/*==========
|
||||
shooter_think
|
||||
==========*/
|
||||
static void() shooter_think =
|
||||
{
|
||||
shooter_use();
|
||||
self.think = shooter_think;
|
||||
self.nextthink = time + self.wait;
|
||||
};
|
||||
|
||||
/*==========
|
||||
shooter_precache
|
||||
==========*/
|
||||
static void() shooter_precache =
|
||||
{
|
||||
if (self.spawnflags & SHOOTER_LASER)
|
||||
{
|
||||
precache_model2 ("progs/laser.mdl");
|
||||
precache_sound2 ("enforcer/enfire.wav");
|
||||
precache_sound2 ("enforcer/enfstop.wav");
|
||||
}
|
||||
else if (self.spawnflags & SHOOTER_SUPERSPIKE)
|
||||
precache_sound ("weapons/spike2.wav");
|
||||
else
|
||||
precache_sound("weapons/rocket1i.wav");
|
||||
};
|
||||
|
||||
/*QUAKED trap_spikeshooter (1 .5 0) (-8 -8 -8) (8 8 8) SUPERSPIKE LASER
|
||||
Fires projectiles when triggered.
|
||||
|
||||
Keys:
|
||||
"angle" - direction of movement
|
||||
|
||||
Spawnflags:
|
||||
If no spawnflag is set, shoots regular nails.
|
||||
SUPERSPIKE - fire supernails
|
||||
LASER - fire enforcer lasers
|
||||
*/
|
||||
void() trap_spikeshooter =
|
||||
{
|
||||
shooter_precache();
|
||||
SetMovedir();
|
||||
self.use = shooter_use;
|
||||
};
|
||||
|
||||
/*QUAKED trap_shooter (1 .5 0) (-8 -8 -8) (8 8 8) SUPERSPIKE LASER
|
||||
Continuously fires projectiles.
|
||||
|
||||
Keys:
|
||||
"angle" - direction of movement
|
||||
"wait" - time between shots
|
||||
"nextthink" - delay on first shot, so shooters can be staggered.
|
||||
|
||||
Spawnflags:
|
||||
If no spawnflag is set, shoots regular nails.
|
||||
SUPERSPIKE - fire supernails
|
||||
LASER - fire enforcer lasers
|
||||
*/
|
||||
void() trap_shooter =
|
||||
{
|
||||
shooter_precache();
|
||||
SetPositiveDefault(wait, 1);
|
||||
self.think = shooter_think;
|
||||
self.nextthink = self.nextthink + self.wait;
|
||||
};
|
||||
58
mod_slipgate/source/server/trigger_changelevel.qc
Normal file
58
mod_slipgate/source/server/trigger_changelevel.qc
Normal file
@@ -0,0 +1,58 @@
|
||||
enumflags { CHANGELEVEL_NO_INTERMISSION };
|
||||
|
||||
void() GotoNextMap;
|
||||
void() StartIntermission;
|
||||
|
||||
/*==========
|
||||
changelevel_touch
|
||||
==========*/
|
||||
void() changelevel_touch =
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
if (other.health <= 0)
|
||||
return;
|
||||
|
||||
if ((cvar("noexit") && (mapname != "start") && deathmatch))
|
||||
{
|
||||
if (cvar("noexit") == 2)
|
||||
Damage (other, self, self, 50000);
|
||||
return;
|
||||
}
|
||||
|
||||
if (coop || deathmatch)
|
||||
{
|
||||
bprint (other.netname);
|
||||
bprint (" exited the level\n");
|
||||
}
|
||||
|
||||
nextmap = self.map;
|
||||
activator = other;
|
||||
UseTargets();
|
||||
|
||||
if ((self.spawnflags & CHANGELEVEL_NO_INTERMISSION) && (!deathmatch))
|
||||
{
|
||||
GotoNextMap();
|
||||
return;
|
||||
}
|
||||
|
||||
self.touch = SUB_Null;
|
||||
self.think = StartIntermission;
|
||||
self.nextthink = time + 0.1;
|
||||
};
|
||||
|
||||
/*QUAKED trigger_changelevel (0.5 0.5 0.5) ? NO_INTERMISSION X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
When the player touches this trigger, they get sent to the map listed in the "map" key.
|
||||
Unless the NO_INTERMISSION flag is set, the view will go to the info_intermission spot and display the end of level stats.
|
||||
*/
|
||||
void() trigger_changelevel =
|
||||
{
|
||||
if (!self.map)
|
||||
{
|
||||
objerror("no map");
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
self.touch = changelevel_touch;
|
||||
InitTrigger();
|
||||
};
|
||||
74
mod_slipgate/source/server/trigger_hurt.qc
Normal file
74
mod_slipgate/source/server/trigger_hurt.qc
Normal file
@@ -0,0 +1,74 @@
|
||||
/*==========
|
||||
hurt_touch
|
||||
|
||||
this was seriously bugged in id1. now correctly damages everything touching it.
|
||||
==========*/
|
||||
static void() hurt_touch =
|
||||
{
|
||||
force_retouch = 2;
|
||||
|
||||
if (other.takedamage)
|
||||
{
|
||||
if (other.hurt_time > time)
|
||||
return;
|
||||
Damage (other, self, self, self.dmg);
|
||||
other.hurt_time = time + self.wait;
|
||||
}
|
||||
};
|
||||
|
||||
/*QUAKED trigger_hurt (.5 .5 .5) ? X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
A trigger that damages anything alive that touches it.
|
||||
|
||||
Keys:
|
||||
dmg - damage to deal. default 5.
|
||||
wait - time in seconds between causing damage. default 1
|
||||
*/
|
||||
void() trigger_hurt =
|
||||
{
|
||||
self.touch = hurt_touch;
|
||||
SetPositiveDefault(dmg, 5);
|
||||
SetPositiveDefault(wait, 1);
|
||||
InitTrigger();
|
||||
};
|
||||
|
||||
/*==========
|
||||
void_touch
|
||||
==========*/
|
||||
static void() void_touch =
|
||||
{
|
||||
force_retouch = 2;
|
||||
|
||||
// just remove items and monsters
|
||||
if (other.flags & FL_ITEM || other.flags & FL_MONSTER)
|
||||
{
|
||||
remove(other);
|
||||
return;
|
||||
}
|
||||
|
||||
// insta kill players
|
||||
if (other.flags & FL_CLIENT)
|
||||
{
|
||||
// remove all armor
|
||||
other.items = other.items - (other.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3));
|
||||
other.armortype = other.armorvalue = 0;
|
||||
// remove pent
|
||||
other.items = other.items - other.items & IT_INVULNERABILITY;
|
||||
other.invincible_finished = other.invincible_time = other.invincible_sound = 0;
|
||||
|
||||
// black screen
|
||||
stuffcmd(other, "v_cshift 0 0 0 255\n");
|
||||
|
||||
Damage (other, self, self, other.health);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
/*QUAKED trigger_void (.5 .5 .5) ? X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
A variable sized trigger designed for "void" areas that removes items, projectiles and monsters touching it.
|
||||
Always kills the player regardless of pentagram or armor.
|
||||
*/
|
||||
void() trigger_void =
|
||||
{
|
||||
self.touch = void_touch;
|
||||
InitTrigger();
|
||||
};
|
||||
34
mod_slipgate/source/server/trigger_ladder.qc
Normal file
34
mod_slipgate/source/server/trigger_ladder.qc
Normal file
@@ -0,0 +1,34 @@
|
||||
#define SMALL_FLOAT (float)(__variant)0x00800000i
|
||||
|
||||
/*==========
|
||||
ladder_touch
|
||||
==========*/
|
||||
static void() ladder_touch =
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
if (other.health <= 0)
|
||||
return;
|
||||
|
||||
// check player is facing the right way
|
||||
if (self.movedir)
|
||||
{
|
||||
makevectors (other.angles);
|
||||
if (v_forward * self.movedir < 0)
|
||||
return;
|
||||
}
|
||||
other.flags2 = other.flags2 | FL2_ONLADDER;
|
||||
other.gravity = SMALL_FLOAT; // because setting it to 0 would be normal gravity
|
||||
};
|
||||
|
||||
/*QUAKED trigger_ladder (.5 .5 .5) ? X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
Invisible ladder trigger.
|
||||
When the player is touching this trigger, they can climb by holding jump.
|
||||
If "angle" is set, the player must face that direction to climb the ladder.
|
||||
An angle of 0 is assumed to mean no direction, so use an angle of 360 instead.
|
||||
*/
|
||||
void() trigger_ladder =
|
||||
{
|
||||
InitTrigger();
|
||||
self.touch = ladder_touch;
|
||||
};
|
||||
43
mod_slipgate/source/server/trigger_monsterjump.qc
Normal file
43
mod_slipgate/source/server/trigger_monsterjump.qc
Normal file
@@ -0,0 +1,43 @@
|
||||
/*==========
|
||||
monsterjump_touch
|
||||
==========*/
|
||||
static void() monsterjump_touch =
|
||||
{
|
||||
if (other.flags & (FL_MONSTER | FL_FLY | FL_SWIM) != FL_MONSTER)
|
||||
return;
|
||||
if (other.health <= 0)
|
||||
return;
|
||||
if (self.netname != "")
|
||||
{
|
||||
if (other.classname != self.netname)
|
||||
return;
|
||||
}
|
||||
|
||||
// set XY even if not on ground, so the jump will clear lips
|
||||
other.velocity_x = self.movedir_x * self.speed;
|
||||
other.velocity_y = self.movedir_y * self.speed;
|
||||
if (!(other.flags & FL_ONGROUND))
|
||||
return;
|
||||
other.flags = other.flags - FL_ONGROUND;
|
||||
other.velocity_z = self.height;
|
||||
};
|
||||
|
||||
/*QUAKED trigger_monsterjump (.5 .5 .5) ? X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
Walking monsters that touch this will jump at a set "speed" and "height" according to "angle"
|
||||
|
||||
Keys:
|
||||
"angle" - angle to fling monsters
|
||||
"speed" - defaults to 200, the speed thrown forward
|
||||
"height" - defaults to 200, the speed thrown upwards
|
||||
"netname" - only monsters with this classname will be affected, e.g. "monster_shambler"
|
||||
*/
|
||||
void() trigger_monsterjump =
|
||||
{
|
||||
if (!self.angles)
|
||||
self.angles = '0 360 0';
|
||||
|
||||
SetPositiveDefault(speed, 200);
|
||||
SetPositiveDefault(height, 200);
|
||||
self.touch = monsterjump_touch;
|
||||
InitTrigger();
|
||||
};
|
||||
49
mod_slipgate/source/server/trigger_push.qc
Normal file
49
mod_slipgate/source/server/trigger_push.qc
Normal file
@@ -0,0 +1,49 @@
|
||||
static enumflags { PUSH_ONCE, PUSH_NO_SOUND };
|
||||
|
||||
/*==========
|
||||
push_touch
|
||||
==========*/
|
||||
static void() push_touch =
|
||||
{
|
||||
if (other.classname == "grenade")
|
||||
other.velocity = self.speed * self.movedir * 10;
|
||||
else if (other.health > 0)
|
||||
{
|
||||
other.velocity = self.speed * self.movedir * 10;
|
||||
if (other.classname == "player" && !(self.spawnflags & PUSH_NO_SOUND))
|
||||
{
|
||||
if (other.fly_sound < time)
|
||||
{
|
||||
other.fly_sound = time + 1.5;
|
||||
sound (other, CHAN_AUTO, self.noise, 1, ATTN_NORM);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (self.spawnflags & PUSH_ONCE)
|
||||
{
|
||||
self.solid = SOLID_NOT;
|
||||
self.touch = SUB_Null;
|
||||
self.think = SUB_Remove;
|
||||
self.nextthink = time;
|
||||
}
|
||||
};
|
||||
|
||||
/*QUAKED trigger_push (.5 .5 .5) ? PUSH_ONCE NO_SOUND X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
Pushes the player in the direction of "angle" at "speed" and makes the flying wind sound.
|
||||
Note that "speed" will be multiplied by a factor of 10, so 30 = 300
|
||||
Use an "angle" of 360 for 0, -1 for up and -2 for down.
|
||||
Set "noise" for a custom sound
|
||||
Set PUSH_ONCE to remove after first use.
|
||||
Set NO_SOUND to make silent.
|
||||
*/
|
||||
void() trigger_push =
|
||||
{
|
||||
if (!(self.spawnflags & PUSH_NO_SOUND))
|
||||
{
|
||||
SetStringDefault(noise, "ambience/windfly.wav");
|
||||
precache_sound (self.noise);
|
||||
}
|
||||
SetPositiveDefault(speed, 1000);
|
||||
self.touch = push_touch;
|
||||
InitTrigger();
|
||||
};
|
||||
198
mod_slipgate/source/server/trigger_teleport.qc
Normal file
198
mod_slipgate/source/server/trigger_teleport.qc
Normal file
@@ -0,0 +1,198 @@
|
||||
static enumflags { TELEPORT_PLAYER_ONLY, TELEPORT_SILENT };
|
||||
|
||||
/*==========
|
||||
play_teleport
|
||||
==========*/
|
||||
static void() play_teleport =
|
||||
{
|
||||
float r = randomrange(5);
|
||||
if (r == 0)
|
||||
sound (self, CHAN_VOICE, "misc/r_tele1.wav", 1, ATTN_NORM);
|
||||
else if (r == 1)
|
||||
sound (self, CHAN_VOICE, "misc/r_tele2.wav", 1, ATTN_NORM);
|
||||
else if (r == 2)
|
||||
sound (self, CHAN_VOICE, "misc/r_tele3.wav", 1, ATTN_NORM);
|
||||
else if (r == 3)
|
||||
sound (self, CHAN_VOICE, "misc/r_tele4.wav", 1, ATTN_NORM);
|
||||
else
|
||||
sound (self, CHAN_VOICE, "misc/r_tele5.wav", 1, ATTN_NORM);
|
||||
|
||||
remove(self);
|
||||
};
|
||||
|
||||
/*==========
|
||||
spawn_tfog
|
||||
==========*/
|
||||
void(vector org) spawn_tfog =
|
||||
{
|
||||
te_teleport(org);
|
||||
|
||||
entity e = spawn();
|
||||
setorigin(e, org);
|
||||
e.think = play_teleport;
|
||||
e.nextthink = time + 0.2; // delay sound slightly
|
||||
};
|
||||
|
||||
/*==========
|
||||
tdeath_touch
|
||||
==========*/
|
||||
static void() tdeath_touch =
|
||||
{
|
||||
if (!other.takedamage)
|
||||
return;
|
||||
if (other == self.owner) // the engine doesn't respect .owner for triggers!
|
||||
return;
|
||||
|
||||
if (other.classname == "player")
|
||||
{
|
||||
// monsters can't telefrag players
|
||||
if (self.owner.flags & FL_MONSTER)
|
||||
{
|
||||
Damage (self.owner, self, self, 50000);
|
||||
return;
|
||||
}
|
||||
|
||||
// check for pentagram on the player on the spot
|
||||
if (other.items & IT_INVULNERABILITY)
|
||||
{
|
||||
// check for pentagram on both players
|
||||
if (self.owner.items & IT_INVULNERABILITY)
|
||||
{
|
||||
// kill the player on the spot
|
||||
self.classname = "teledeath3";
|
||||
other.items = other.items - IT_INVULNERABILITY;
|
||||
other.invincible_time = other.invincible_finished = 0;
|
||||
Damage (other, self, self, 50000);
|
||||
}
|
||||
else
|
||||
{
|
||||
// kill the teleporting player
|
||||
self.classname = "teledeath2";
|
||||
Damage (self.owner, self, self, 50000);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
Damage(other, self, self, 50000);
|
||||
};
|
||||
|
||||
/*==========
|
||||
spawn_tdeath
|
||||
==========*/
|
||||
void(vector org, entity who) spawn_tdeath =
|
||||
{
|
||||
force_retouch = 2; // make sure even still objects get hit
|
||||
|
||||
entity e = spawn();
|
||||
e.classname = "teledeath";
|
||||
e.owner = who;
|
||||
e.movetype = MOVETYPE_NONE;
|
||||
e.solid = SOLID_TRIGGER;
|
||||
setsize (e, who.mins - '1 1 1', who.maxs + '1 1 1');
|
||||
setorigin (e, org);
|
||||
e.touch = tdeath_touch;
|
||||
e.think = SUB_Remove;
|
||||
e.nextthink = time + 0.2;
|
||||
};
|
||||
|
||||
/*==========
|
||||
teleport_touch
|
||||
==========*/
|
||||
static void() teleport_touch =
|
||||
{
|
||||
if (self.spawnflags & TELEPORT_PLAYER_ONLY)
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
}
|
||||
if (other.health <= 0)
|
||||
return;
|
||||
if (other.solid != SOLID_SLIDEBOX) // only players/monsters
|
||||
return;
|
||||
|
||||
// look for the destination spot
|
||||
entity t = find (world, targetname, self.target);
|
||||
if (!t)
|
||||
{
|
||||
objerror ("couldn't find target");
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
|
||||
// some maps use things other then info_teleport_destination as targets for
|
||||
// teleporters. just print a warning.
|
||||
if (developer > 1)
|
||||
{
|
||||
if (t.classname != "info_teleport_destination")
|
||||
{
|
||||
dprint("warning: teleport destination is ");
|
||||
dprint(t.classname);
|
||||
dprint(" at ");
|
||||
dprint(vtos(t.origin));
|
||||
dprint("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// fire targets
|
||||
activator = other;
|
||||
UseTargets();
|
||||
|
||||
// spawn teleport flash at source and destination
|
||||
spawn_tfog (other.origin);
|
||||
makevectors (t.angles);
|
||||
vector org = t.origin + '0 0 27';
|
||||
spawn_tfog (org + v_forward * 32);
|
||||
spawn_tdeath(org, other);
|
||||
|
||||
// move the player/monster
|
||||
setorigin (other, org);
|
||||
other.angles = t.angles;
|
||||
other.flags = other.flags - (other.flags & FL_ONGROUND);
|
||||
if (other.classname == "player")
|
||||
{
|
||||
other.fixangle = TRUE; // turn this way immediately
|
||||
other.teleport_time = time + 0.7; // don't let player move back into teleporter
|
||||
other.velocity = v_forward * 300; // give a forwards push
|
||||
}
|
||||
};
|
||||
|
||||
/*==========
|
||||
teleport_use
|
||||
|
||||
using a teleporter makes it active. it then behaves like any other teleporter.
|
||||
==========*/
|
||||
static void() teleport_use =
|
||||
{
|
||||
force_retouch = 2; // make sure even still objects get hit
|
||||
self.touch = teleport_touch;
|
||||
self.use = SUB_Null;
|
||||
};
|
||||
|
||||
/*QUAKED trigger_teleport (.5 .5 .5) ? PLAYER_ONLY SILENT X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
Variable sized trigger that teleports players and monsters to a destination marker.
|
||||
"target" must be set to an info_teleport_destination with a matching "targetname" field.
|
||||
If the trigger_teleport has a "targetname", it will only teleport entities once it has been triggered.
|
||||
This is used in id1 for teleporting monsters - this has been obsoleted by the MONSTER_TELEPORT flag.
|
||||
|
||||
Spawnflags:
|
||||
PLAYER_ONLY - just players, not monsters
|
||||
SILENT - don't spawn ambient teleporter noise
|
||||
*/
|
||||
void() trigger_teleport =
|
||||
{
|
||||
if (!self.target)
|
||||
{
|
||||
objerror ("no target");
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
if (self.targetname != "")
|
||||
self.use = teleport_use;
|
||||
else
|
||||
self.touch = teleport_touch;
|
||||
|
||||
if (!(self.spawnflags & TELEPORT_SILENT))
|
||||
ambient_teleport();
|
||||
|
||||
InitTrigger();
|
||||
};
|
||||
349
mod_slipgate/source/server/triggers.qc
Normal file
349
mod_slipgate/source/server/triggers.qc
Normal file
@@ -0,0 +1,349 @@
|
||||
static enumflags { TRIGGER_NOTOUCH, TRIGGER_START_OFF };
|
||||
|
||||
/*==========
|
||||
InitTrigger
|
||||
==========*/
|
||||
void() InitTrigger =
|
||||
{
|
||||
// if angles are set, the trigger is a one way touch
|
||||
if (self.angles != '0 0 0')
|
||||
SetMovedir();
|
||||
|
||||
// link into world
|
||||
self.movetype = MOVETYPE_NONE;
|
||||
self.solid = SOLID_TRIGGER;
|
||||
setmodel (self, self.model);
|
||||
|
||||
// make invisible
|
||||
self.modelindex = 0;
|
||||
self.model = "";
|
||||
};
|
||||
|
||||
/*==========
|
||||
trigger_reactivate
|
||||
==========*/
|
||||
static void() trigger_reactivate =
|
||||
{
|
||||
// if shootable, make solid again
|
||||
if (self.max_health)
|
||||
{
|
||||
self.health = self.max_health;
|
||||
self.takedamage = DAMAGE_YES;
|
||||
self.solid = SOLID_BBOX;
|
||||
setorigin(self, self.origin); // link into world
|
||||
}
|
||||
};
|
||||
|
||||
/*==========
|
||||
trigger_fire
|
||||
==========*/
|
||||
void() trigger_fire =
|
||||
{
|
||||
// already triggered
|
||||
if (self.nextthink > time)
|
||||
return;
|
||||
|
||||
// bump secret counter
|
||||
if (self.classname == "trigger_secret")
|
||||
{
|
||||
if (self.enemy.classname != "player")
|
||||
return;
|
||||
found_secrets = found_secrets + 1;
|
||||
WriteByte (MSG_ALL, SVC_FOUNDSECRET);
|
||||
}
|
||||
|
||||
if (self.noise != "")
|
||||
sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
|
||||
|
||||
// fire targets
|
||||
activator = self.enemy;
|
||||
UseTargets();
|
||||
|
||||
if (self.wait > 0)
|
||||
{
|
||||
self.think = trigger_reactivate;
|
||||
self.nextthink = time + self.wait;
|
||||
return;
|
||||
}
|
||||
|
||||
remove(self);
|
||||
};
|
||||
|
||||
/*==========
|
||||
trigger_killed
|
||||
==========*/
|
||||
void(entity inflictor, entity attacker) trigger_killed =
|
||||
{
|
||||
self.takedamage = DAMAGE_NO;
|
||||
self.enemy = attacker;
|
||||
trigger_fire();
|
||||
};
|
||||
|
||||
/*==========
|
||||
trigger_use
|
||||
==========*/
|
||||
void() trigger_use =
|
||||
{
|
||||
self.enemy = activator;
|
||||
trigger_fire();
|
||||
};
|
||||
|
||||
/*==========
|
||||
trigger_touch
|
||||
==========*/
|
||||
void() trigger_touch =
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
if (other.health <= 0)
|
||||
return;
|
||||
|
||||
// check player is facing the right way
|
||||
if (self.movedir)
|
||||
{
|
||||
makevectors (other.angles);
|
||||
if (v_forward * self.movedir < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
self.enemy = other;
|
||||
trigger_fire();
|
||||
};
|
||||
|
||||
/*QUAKED trigger_multiple (.5 .5 .5) ? NOTOUCH X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
Variable sized repeatable trigger.
|
||||
|
||||
Keys:
|
||||
"target" - entities to trigger upon firing
|
||||
"killtarget" - entities to remove upon firing
|
||||
"message" - will be printed to player upon activation
|
||||
"delay" - will wait after activation before firing
|
||||
"health" - if set, trigger must be killed to activate
|
||||
"wait" - time between triggers. default 0.2
|
||||
"sounds" -
|
||||
0) none
|
||||
1) secret
|
||||
2) beep beep
|
||||
3) large switch
|
||||
"angle" - player must be facing this direction to activate the trigger.
|
||||
0 is assumed to mean no restriction, so use 360 for an angle of 0.
|
||||
|
||||
Spawnflags:
|
||||
If NOTOUCH is set, the trigger is only fired by other entities, not by touching.
|
||||
NOTOUCH has been obsoleted by trigger_relay.
|
||||
*/
|
||||
void() trigger_multiple =
|
||||
{
|
||||
if (self.sounds == 1)
|
||||
self.noise = "misc/secret.wav";
|
||||
else if (self.sounds == 2)
|
||||
self.noise = "misc/talk.wav";
|
||||
else if (self.sounds == 3)
|
||||
self.noise = "misc/trigger1.wav";
|
||||
if (self.noise != "")
|
||||
precache_sound(self.noise);
|
||||
|
||||
SetFloatDefault(wait, 0.2);
|
||||
self.use = trigger_use;
|
||||
InitTrigger();
|
||||
|
||||
// shootable trigger
|
||||
if (self.health > 0)
|
||||
{
|
||||
if (self.spawnflags & TRIGGER_NOTOUCH)
|
||||
{
|
||||
objerror ("health and NOTOUCH doesn't make sense\n");
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
self.max_health = self.health;
|
||||
self.th_die = trigger_killed;
|
||||
self.takedamage = DAMAGE_YES;
|
||||
self.solid = SOLID_BBOX;
|
||||
setorigin (self, self.origin); // make sure it links into the world
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(self.spawnflags & TRIGGER_NOTOUCH))
|
||||
self.touch = trigger_touch;
|
||||
};
|
||||
|
||||
/*QUAKED trigger_once (.5 .5 .5) ? NOTOUCH X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
Variable sized trigger. Triggers once, then removes itself.
|
||||
|
||||
Keys:
|
||||
"target" - entities to trigger upon firing
|
||||
"killtarget" - entities to remove upon firing
|
||||
"message" - will be printed to player upon activation
|
||||
"delay" - will wait after activation before firing
|
||||
"health" - if set, trigger must be killed to activate
|
||||
"wait" - time between triggers. default 0.2
|
||||
"sounds" -
|
||||
0) none
|
||||
1) secret
|
||||
2) beep beep
|
||||
3) large switch
|
||||
"angle" - player must be facing this direction to activate the trigger.
|
||||
0 is assumed to mean no restriction, so use 360 for an angle of 0.
|
||||
|
||||
Spawnflags:
|
||||
If NOTOUCH is set, the trigger is only fired by other entities, not by touching.
|
||||
NOTOUCH has been obsoleted by trigger_relay.
|
||||
*/
|
||||
void() trigger_once =
|
||||
{
|
||||
self.wait = -1;
|
||||
trigger_multiple();
|
||||
};
|
||||
|
||||
/*QUAKED trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8)
|
||||
This fixed size trigger cannot be touched, it can only be fired by other events.
|
||||
It can contain targets, killtargets, delays, and messages.
|
||||
*/
|
||||
void() trigger_relay =
|
||||
{
|
||||
self.use = UseTargets;
|
||||
};
|
||||
|
||||
/*QUAKED trigger_secret (.5 .5 .5) ? NOTOUCH X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
Variable sized secret counter trigger. Triggers once, then removes itself.
|
||||
|
||||
Keys:
|
||||
"target" - entities to trigger upon firing
|
||||
"killtarget" - entities to remove upon firing
|
||||
"message" - will be printed to player upon activation. default "You found a secret area!"
|
||||
"delay" - will wait after activation before firing
|
||||
"health" - if set, trigger must be killed to activate
|
||||
"sounds" -
|
||||
1) secret (default)
|
||||
2) beep beep
|
||||
3) large switch
|
||||
"angle" - player must be facing this direction to activate the trigger.
|
||||
0 is assumed to mean no restriction, so use 360 for an angle of 0.
|
||||
|
||||
Spawnflags:
|
||||
If NOTOUCH is set, the trigger is only fired by other entities, not by touching.
|
||||
NOTOUCH has been obsoleted by trigger_relay.
|
||||
*/
|
||||
void() trigger_secret =
|
||||
{
|
||||
total_secrets = total_secrets + 1;
|
||||
self.wait = -1;
|
||||
SetStringDefault(message, "You found a secret area!");
|
||||
SetPositiveDefault(sounds, 1);
|
||||
trigger_multiple();
|
||||
};
|
||||
|
||||
static enumflags { COUNTER_NOMESSAGE };
|
||||
|
||||
/*==========
|
||||
counter_use
|
||||
==========*/
|
||||
void() counter_use =
|
||||
{
|
||||
self.count = self.count - 1;
|
||||
|
||||
// more to go
|
||||
if (self.count > 0)
|
||||
{
|
||||
if (activator.classname == "player")
|
||||
{
|
||||
if (!(self.spawnflags & COUNTER_NOMESSAGE))
|
||||
{
|
||||
if (self.count > 3)
|
||||
centerprint (activator, "There are more to go...");
|
||||
else if (self.count == 3)
|
||||
centerprint (activator, "Only 3 more to go...");
|
||||
else if (self.count == 2)
|
||||
centerprint (activator, "Only 2 more to go...");
|
||||
else
|
||||
centerprint (activator, "Only 1 more to go...");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
self.use = SUB_Null; // don't allow further triggering
|
||||
|
||||
if (activator.classname == "player")
|
||||
{
|
||||
if (!(self.spawnflags & COUNTER_NOMESSAGE))
|
||||
centerprint(activator, "Sequence completed!");
|
||||
}
|
||||
|
||||
// fire targets
|
||||
self.enemy = activator;
|
||||
trigger_fire();
|
||||
};
|
||||
|
||||
/*QUAKED trigger_counter (.5 .5 .5) ? NOMESSAGE X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
Acts as an intermediary for an action that takes multiple inputs - cannot be interacted with directly.
|
||||
It will print "Only X more to go.." when triggered and "Sequence completed!" when finished.
|
||||
After the counter has been triggered "count" times (default 2), it will fire all of it's targets and remove itself.
|
||||
|
||||
Spawnflags:
|
||||
NOMESSAGE - don't display any messages
|
||||
*/
|
||||
void() trigger_counter =
|
||||
{
|
||||
SetPositiveDefault(count, 2);
|
||||
self.use = counter_use;
|
||||
};
|
||||
|
||||
/*==========
|
||||
skill_touch
|
||||
==========*/
|
||||
static void() skill_touch =
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
if (other.health <= 0)
|
||||
return;
|
||||
cvar_set("skill", self.message);
|
||||
};
|
||||
|
||||
/*QUAKED trigger_setskill (.5 .5 .5) ? X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
Trigger that sets "skill" to the value of "message".
|
||||
*/
|
||||
void() trigger_setskill =
|
||||
{
|
||||
self.touch = skill_touch;
|
||||
InitTrigger();
|
||||
};
|
||||
|
||||
/*==========
|
||||
onlyregistered_touch
|
||||
==========*/
|
||||
static void() onlyregistered_touch =
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
if (other.health <= 0)
|
||||
return;
|
||||
if (self.attack_finished > time)
|
||||
return;
|
||||
self.attack_finished = time + 2;
|
||||
if (cvar("registered"))
|
||||
{
|
||||
self.message = "";
|
||||
activator = other;
|
||||
UseTargets ();
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.message != "")
|
||||
{
|
||||
centerprint (other, self.message);
|
||||
sound (other, CHAN_BODY, "misc/talk.wav", 1, ATTN_NORM);
|
||||
}
|
||||
};
|
||||
|
||||
/*QUAKED trigger_onlyregistered (.5 .5 .5) ? X X X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
||||
Only fires if playing the registered version, otherwise prints the message.
|
||||
*/
|
||||
void() trigger_onlyregistered =
|
||||
{
|
||||
self.touch = onlyregistered_touch;
|
||||
InitTrigger();
|
||||
};
|
||||
189
mod_slipgate/source/server/util.qc
Normal file
189
mod_slipgate/source/server/util.qc
Normal file
@@ -0,0 +1,189 @@
|
||||
/*==========
|
||||
SetStringDefault
|
||||
==========*/
|
||||
void(.string field, string val) SetStringDefault =
|
||||
{
|
||||
if (!self.field)
|
||||
self.field = val;
|
||||
};
|
||||
|
||||
/*==========
|
||||
SetFloatDefault
|
||||
==========*/
|
||||
void(.float field, float val) SetFloatDefault =
|
||||
{
|
||||
if (self.field == 0)
|
||||
self.field = val;
|
||||
};
|
||||
|
||||
/*==========
|
||||
SetPositiveDefault
|
||||
==========*/
|
||||
void(.float field, float val) SetPositiveDefault =
|
||||
{
|
||||
if (self.field <= 0)
|
||||
self.field = val;
|
||||
};
|
||||
|
||||
/*==========
|
||||
realorigin
|
||||
==========*/
|
||||
vector(entity e) realorigin =
|
||||
{
|
||||
return 0.5 * (e.absmin + e.absmax);
|
||||
};
|
||||
|
||||
/*==========
|
||||
anglemod
|
||||
correct an angle so it's between 0 and 359
|
||||
==========*/
|
||||
float(float v) anglemod =
|
||||
{
|
||||
return v - floor(v/360) * 360;
|
||||
};
|
||||
|
||||
/*==========
|
||||
angcomp
|
||||
calculate the difference between two angles
|
||||
==========*/
|
||||
float (float y1, float y2) angcomp =
|
||||
{
|
||||
y1 = anglemod(y1);
|
||||
y2 = anglemod(y2);
|
||||
float answer = y1 - y2;
|
||||
if (answer > 180)
|
||||
answer = answer - 360;
|
||||
else if (answer < -180)
|
||||
answer = answer + 360;
|
||||
return answer;
|
||||
};
|
||||
|
||||
/*==========
|
||||
crandom
|
||||
returns -1 to +1
|
||||
==========*/
|
||||
float() crandom =
|
||||
{
|
||||
return 2 * (random() - 0.5);
|
||||
};
|
||||
|
||||
/*==========
|
||||
randomvec
|
||||
returns a random vector with all 3 components between -1 and +1
|
||||
==========*/
|
||||
vector() randomvec =
|
||||
{
|
||||
return [crandom(), crandom(), crandom()];
|
||||
};
|
||||
|
||||
/*==========
|
||||
randomrange
|
||||
returns a whole number between 0 and range - 1
|
||||
==========*/
|
||||
float(float range) randomrange =
|
||||
{
|
||||
if (range < 1)
|
||||
return 0;
|
||||
float result = floor(random() * range);
|
||||
// random can return 1 in some engines
|
||||
if (result == range)
|
||||
return range - 1;
|
||||
else
|
||||
return result;
|
||||
};
|
||||
|
||||
/*==========
|
||||
spawn_debug_marker
|
||||
==========*/
|
||||
void(vector org) spawn_debug_marker =
|
||||
{
|
||||
if (!developer)
|
||||
return;
|
||||
|
||||
entity e = spawn();
|
||||
e.classname = "DebugMarker";
|
||||
e.solid = SOLID_NOT;
|
||||
e.movetype = MOVETYPE_NONE;
|
||||
setmodel(e, "progs/s_bubble.spr");
|
||||
setsize(e, '0 0 0', '0 0 0');
|
||||
setorigin(e, org);
|
||||
|
||||
e.think = SUB_Remove;
|
||||
e.nextthink = time + 5;
|
||||
};
|
||||
|
||||
static vector v_forward2, v_up2, v_right2;
|
||||
|
||||
/*==========
|
||||
save_vectors
|
||||
==========*/
|
||||
static inline void() save_vectors =
|
||||
{
|
||||
v_forward2 = v_forward;
|
||||
v_up2 = v_up;
|
||||
v_right2 = v_right;
|
||||
};
|
||||
|
||||
/*==========
|
||||
restore_vectors
|
||||
==========*/
|
||||
static inline void() restore_vectors =
|
||||
{
|
||||
v_forward = v_forward2;
|
||||
v_up = v_up2;
|
||||
v_right = v_right2;
|
||||
};
|
||||
|
||||
/*==========
|
||||
cos
|
||||
==========*/
|
||||
float(float n) cos =
|
||||
{
|
||||
save_vectors();
|
||||
|
||||
vector ang = [0, n, 0];
|
||||
makevectors(ang);
|
||||
float result = v_forward_x;
|
||||
|
||||
restore_vectors();
|
||||
return result;
|
||||
};
|
||||
|
||||
/*==========
|
||||
sin
|
||||
==========*/
|
||||
float(float n) sin =
|
||||
{
|
||||
save_vectors();
|
||||
|
||||
vector ang = [0, n, 0];
|
||||
makevectors(ang);
|
||||
float result = v_forward_y;
|
||||
|
||||
restore_vectors();
|
||||
return result;
|
||||
};
|
||||
|
||||
/*==========
|
||||
tan
|
||||
==========*/
|
||||
float(float n) tan =
|
||||
{
|
||||
save_vectors();
|
||||
|
||||
vector ang = [0, n, 0];
|
||||
makevectors(ang);
|
||||
float result = v_forward_y / v_forward_x;
|
||||
|
||||
restore_vectors();
|
||||
return result;
|
||||
};
|
||||
|
||||
/*==========
|
||||
atan2
|
||||
==========*/
|
||||
float(float y, float x) atan2 =
|
||||
{
|
||||
vector ang = [x, y, 0];
|
||||
return vectoyaw(ang);
|
||||
};
|
||||
108
mod_slipgate/source/server/w_shotguns.qc
Normal file
108
mod_slipgate/source/server/w_shotguns.qc
Normal file
@@ -0,0 +1,108 @@
|
||||
static entity multi_ent;
|
||||
static float multi_damage;
|
||||
|
||||
/*==========
|
||||
ClearMultiDamage
|
||||
==========*/
|
||||
static void() ClearMultiDamage =
|
||||
{
|
||||
multi_ent = world;
|
||||
multi_damage = 0;
|
||||
};
|
||||
|
||||
/*==========
|
||||
ApplyMultiDamage
|
||||
==========*/
|
||||
static void() ApplyMultiDamage =
|
||||
{
|
||||
if (!multi_ent)
|
||||
return;
|
||||
Damage (multi_ent, self, self, multi_damage);
|
||||
};
|
||||
|
||||
/*==========
|
||||
AddMultiDamage
|
||||
==========*/
|
||||
static void(entity hit, float damage) AddMultiDamage =
|
||||
{
|
||||
if (!hit)
|
||||
return;
|
||||
|
||||
if (hit != multi_ent)
|
||||
{
|
||||
ApplyMultiDamage();
|
||||
multi_damage = damage;
|
||||
multi_ent = hit;
|
||||
}
|
||||
else
|
||||
multi_damage = multi_damage + damage;
|
||||
};
|
||||
|
||||
/*==========
|
||||
TraceAttack
|
||||
==========*/
|
||||
static void(float damage, vector dir) TraceAttack =
|
||||
{
|
||||
vector org = trace_endpos - dir*4;
|
||||
if (trace_ent.takedamage)
|
||||
{
|
||||
vector vel = normalize(dir + v_up*crandom() + v_right*crandom());
|
||||
vel = vel + 2 * trace_plane_normal;
|
||||
vel = vel * 4;
|
||||
|
||||
if (trace_ent.solid == SOLID_BSP)
|
||||
particle(org, vel, trace_ent.colour, damage);
|
||||
else
|
||||
SpawnBlood (org, vel, damage);
|
||||
AddMultiDamage (trace_ent, damage);
|
||||
}
|
||||
else
|
||||
te_gunshot(org);
|
||||
};
|
||||
|
||||
/*==========
|
||||
FireBullets
|
||||
==========*/
|
||||
void(float shotcount, vector dir, vector spread) FireBullets =
|
||||
{
|
||||
makevectors(self.v_angle);
|
||||
vector src = self.origin + v_forward*10;
|
||||
src_z = self.absmin_z + self.size_z * 0.7;
|
||||
|
||||
ClearMultiDamage();
|
||||
while (shotcount > 0)
|
||||
{
|
||||
vector direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
|
||||
traceline (src, src + direction*2048, FALSE, self);
|
||||
if (trace_fraction != 1.0)
|
||||
TraceAttack (4, direction);
|
||||
shotcount = shotcount - 1;
|
||||
}
|
||||
ApplyMultiDamage();
|
||||
};
|
||||
|
||||
/*==========
|
||||
W_FireShotgun
|
||||
==========*/
|
||||
void() W_FireShotgun =
|
||||
{
|
||||
sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);
|
||||
self.punchangle_x = -2;
|
||||
self.currentammo = self.ammo_shells = self.ammo_shells - 1;
|
||||
|
||||
vector dir = aim (self, 100000);
|
||||
FireBullets (6, dir, '0.04 0.04 0');
|
||||
};
|
||||
|
||||
/*==========
|
||||
W_FireSuperShotgun
|
||||
==========*/
|
||||
void() W_FireSuperShotgun =
|
||||
{
|
||||
sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);
|
||||
self.punchangle_x = -4;
|
||||
self.currentammo = self.ammo_shells = self.ammo_shells - 2;
|
||||
|
||||
vector dir = aim (self, 100000);
|
||||
FireBullets (14, dir, '0.14 0.08 0');
|
||||
};
|
||||
1090
mod_slipgate/source/server/waypoints.qc
Normal file
1090
mod_slipgate/source/server/waypoints.qc
Normal file
File diff suppressed because it is too large
Load Diff
829
mod_slipgate/source/server/weapons.qc
Normal file
829
mod_slipgate/source/server/weapons.qc
Normal file
@@ -0,0 +1,829 @@
|
||||
/*==========
|
||||
W_RankForWeapon
|
||||
|
||||
used by W_DeathmatchWeapon, returns a rank for a weapon
|
||||
==========*/
|
||||
float(entity player, float w) W_RankForWeapon =
|
||||
{
|
||||
if (w == IT_LIGHTNING && player.ammo_cells)
|
||||
return 1;
|
||||
if (w == IT_ROCKET_LAUNCHER && player.ammo_rockets)
|
||||
return 2;
|
||||
if (w == IT_SUPER_NAILGUN && player.ammo_nails > 1)
|
||||
return 3;
|
||||
if (w == IT_GRENADE_LAUNCHER && player.ammo_rockets)
|
||||
return 4;
|
||||
if (w == IT_SUPER_SHOTGUN && player.ammo_shells > 1)
|
||||
return 5;
|
||||
if (w == IT_NAILGUN && player.ammo_nails)
|
||||
return 6;
|
||||
if (w == IT_SHOTGUN && player.ammo_shells)
|
||||
return 7;
|
||||
return 8;
|
||||
};
|
||||
|
||||
/*==========
|
||||
W_DeathmatchWeapon
|
||||
|
||||
compares two weapons and returns the best one
|
||||
only used in deathmatch
|
||||
==========*/
|
||||
float(entity player, float old, float new) W_DeathmatchWeapon =
|
||||
{
|
||||
float or = W_RankForWeapon(player, old);
|
||||
float nr = W_RankForWeapon(player, new);
|
||||
if (nr < or)
|
||||
return new;
|
||||
else
|
||||
return old;
|
||||
};
|
||||
|
||||
/*==========
|
||||
W_BoundAmmo
|
||||
|
||||
caps player ammo at the max allowed
|
||||
==========*/
|
||||
void(entity player) W_BoundAmmo =
|
||||
{
|
||||
if (player.ammo_shells > 100)
|
||||
player.ammo_shells = 100;
|
||||
if (player.ammo_nails > 200)
|
||||
player.ammo_nails = 200;
|
||||
if (player.ammo_rockets > 100)
|
||||
player.ammo_rockets = 100;
|
||||
if (player.ammo_cells > 100)
|
||||
player.ammo_cells = 100;
|
||||
};
|
||||
|
||||
/*==========
|
||||
W_BestWeapon
|
||||
|
||||
returns the players best weapon
|
||||
to avoid self damage:
|
||||
does not auto-switch to GL or RL
|
||||
does not auto-switch to Thunderbolt if underwater
|
||||
==========*/
|
||||
float(entity player) W_BestWeapon =
|
||||
{
|
||||
if ((player.waterlevel < 2) && (player.ammo_cells > 0) && (player.items & IT_LIGHTNING))
|
||||
return IT_LIGHTNING;
|
||||
if ((player.ammo_nails > 1) && (player.items & IT_SUPER_NAILGUN))
|
||||
return IT_SUPER_NAILGUN;
|
||||
if ((player.ammo_shells > 1) && (player.items & IT_SUPER_SHOTGUN))
|
||||
return IT_SUPER_SHOTGUN;
|
||||
if ((player.ammo_nails > 1) && (player.items & IT_NAILGUN))
|
||||
return IT_NAILGUN;
|
||||
if ((player.ammo_shells > 0) && (player.items & IT_SHOTGUN))
|
||||
return IT_SHOTGUN;
|
||||
return IT_AXE;
|
||||
};
|
||||
|
||||
/*==========
|
||||
W_SetCurrentAmmo
|
||||
|
||||
update the hud with the correct ammo icon and count
|
||||
updates .currentammo and .items
|
||||
==========*/
|
||||
void(entity player) W_SetCurrentAmmo =
|
||||
{
|
||||
player.currentammo = 0;
|
||||
player.items = player.items - (player.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS));
|
||||
if (player.weapon == IT_SHOTGUN || player.weapon == IT_SUPER_SHOTGUN)
|
||||
{
|
||||
player.currentammo = player.ammo_shells;
|
||||
player.items = player.items | IT_SHELLS;
|
||||
}
|
||||
else if (player.weapon == IT_NAILGUN || player.weapon == IT_SUPER_NAILGUN)
|
||||
{
|
||||
player.currentammo = player.ammo_nails;
|
||||
player.items = player.items | IT_NAILS;
|
||||
}
|
||||
else if (player.weapon == IT_GRENADE_LAUNCHER || player.weapon == IT_ROCKET_LAUNCHER)
|
||||
{
|
||||
player.currentammo = player.ammo_rockets;
|
||||
player.items = player.items | IT_ROCKETS;
|
||||
}
|
||||
else if (player.weapon == IT_LIGHTNING)
|
||||
{
|
||||
player.currentammo = player.ammo_cells;
|
||||
player.items = player.items | IT_CELLS;
|
||||
}
|
||||
};
|
||||
|
||||
/*==========
|
||||
W_UpdateWeapon
|
||||
|
||||
updates the weapon view model
|
||||
==========*/
|
||||
void() player_stand;
|
||||
|
||||
void(entity player) W_UpdateWeapon =
|
||||
{
|
||||
if (player.weapon == IT_AXE)
|
||||
player.weaponmodel = "progs/v_axe.mdl";
|
||||
else if (player.weapon == IT_SHOTGUN)
|
||||
player.weaponmodel = "progs/v_shot.mdl";
|
||||
else if (player.weapon == IT_SUPER_SHOTGUN)
|
||||
player.weaponmodel = "progs/v_shot2.mdl";
|
||||
else if (player.weapon == IT_NAILGUN)
|
||||
player.weaponmodel = "progs/v_nail.mdl";
|
||||
else if (player.weapon == IT_SUPER_NAILGUN)
|
||||
player.weaponmodel = "progs/v_nail2.mdl";
|
||||
else if (player.weapon == IT_GRENADE_LAUNCHER)
|
||||
player.weaponmodel = "progs/v_rock.mdl";
|
||||
else if (player.weapon == IT_ROCKET_LAUNCHER)
|
||||
player.weaponmodel = "progs/v_rock2.mdl";
|
||||
else if (player.weapon == IT_LIGHTNING)
|
||||
player.weaponmodel = "progs/v_light.mdl";
|
||||
else
|
||||
player.weaponmodel = "";
|
||||
W_SetCurrentAmmo(player);
|
||||
|
||||
entity oself = self;
|
||||
self = player;
|
||||
player_stand();
|
||||
self = oself;
|
||||
};
|
||||
|
||||
/*==========
|
||||
W_CheckNoAmmo
|
||||
|
||||
returns TRUE if the player has enough ammo for their current gun
|
||||
==========*/
|
||||
float(entity player) W_CheckNoAmmo =
|
||||
{
|
||||
if (!player.weapon)
|
||||
return TRUE;
|
||||
if (player.weapon == IT_AXE)
|
||||
return TRUE;
|
||||
if (player.weapon == IT_SUPER_SHOTGUN || player.weapon == IT_SUPER_NAILGUN)
|
||||
{
|
||||
if (player.currentammo > 1)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
if (player.currentammo > 0)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
/*==========
|
||||
W_FireAxe
|
||||
==========*/
|
||||
void() W_FireAxe =
|
||||
{
|
||||
makevectors (self.v_angle);
|
||||
vector source = self.origin + '0 0 16';
|
||||
traceline (source, source + v_forward*64, FALSE, self);
|
||||
if (trace_fraction == 1.0)
|
||||
return;
|
||||
|
||||
vector org = trace_endpos - v_forward * 4;
|
||||
if (trace_ent.takedamage)
|
||||
{
|
||||
//trace_ent.axhitme = 1;
|
||||
|
||||
vector vel = crandom() * v_right + crandom() * v_up;
|
||||
vel = vel * random() * 4;
|
||||
|
||||
if (trace_ent.classname == "func_breakable")
|
||||
particle(org, vel, trace_ent.colour, 40);
|
||||
else
|
||||
SpawnBlood (org, vel, 40);
|
||||
Damage (trace_ent, self, self, 20);
|
||||
}
|
||||
else
|
||||
{
|
||||
sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_GUNSHOT);
|
||||
WriteCoord (MSG_BROADCAST, org_x);
|
||||
WriteCoord (MSG_BROADCAST, org_y);
|
||||
WriteCoord (MSG_BROADCAST, org_z);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
void() T_MissileTouch =
|
||||
{
|
||||
if (pointcontents(self.origin) == CONTENT_SKY)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
|
||||
float damg = 100 + random() * 20;
|
||||
if (other.takedamage)
|
||||
{
|
||||
if (other.classname == "monster_shambler")
|
||||
damg = damg * 0.5;
|
||||
Damage (other, self, self.owner, damg);
|
||||
}
|
||||
RadiusDamage(self, self.owner, 120, other);
|
||||
|
||||
self.origin = self.origin - 8*normalize(self.velocity);
|
||||
te_explosion(self.origin);
|
||||
BecomeExplosion();
|
||||
};
|
||||
|
||||
void() W_FireRocket =
|
||||
{
|
||||
local entity missile;
|
||||
|
||||
self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
|
||||
|
||||
sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
|
||||
|
||||
self.punchangle_x = -2;
|
||||
|
||||
missile = spawn ();
|
||||
missile.owner = self;
|
||||
missile.movetype = MOVETYPE_FLYMISSILE;
|
||||
missile.solid = SOLID_BBOX;
|
||||
missile.classname = "missile";
|
||||
|
||||
// set missile speed
|
||||
|
||||
makevectors (self.v_angle);
|
||||
//missile.velocity = aim(self, 1000);
|
||||
missile.velocity = v_forward * 1000;
|
||||
missile.angles = vectoangles(missile.velocity);
|
||||
missile.avelocity = [0, 0, 300];
|
||||
|
||||
missile.touch = T_MissileTouch;
|
||||
|
||||
// set missile duration
|
||||
missile.nextthink = time + 5;
|
||||
missile.think = SUB_Remove;
|
||||
|
||||
setmodel (missile, "progs/missile.mdl");
|
||||
setsize (missile, '0 0 0', '0 0 0');
|
||||
setorigin (missile, self.origin + v_forward * 12 + self.view_ofs - v_up * 12);
|
||||
};
|
||||
|
||||
void(vector p1, vector p2, entity from, float damage) LightningDamage =
|
||||
{
|
||||
traceline (p1, p2, FALSE, self);
|
||||
if (trace_ent.takedamage)
|
||||
{
|
||||
particle (trace_endpos, '0 0 100', 225, damage*4);
|
||||
Damage (trace_ent, from, from, damage);
|
||||
}
|
||||
};
|
||||
|
||||
void() W_FireLightning =
|
||||
{
|
||||
if (self.ammo_cells < 1)
|
||||
{
|
||||
self.weapon = W_BestWeapon(self);
|
||||
W_UpdateWeapon(self);
|
||||
return;
|
||||
}
|
||||
|
||||
// explode if under water
|
||||
if (self.waterlevel > 1)
|
||||
{
|
||||
float cells = self.ammo_cells;
|
||||
self.ammo_cells = 0;
|
||||
self.weapon = W_BestWeapon(self);
|
||||
W_UpdateWeapon (self);
|
||||
RadiusDamage (self, self, 35*cells, world);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.t_width < time)
|
||||
{
|
||||
sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
|
||||
self.t_width = time + 0.6;
|
||||
}
|
||||
self.punchangle_x = -2;
|
||||
|
||||
self.currentammo = self.ammo_cells = self.ammo_cells - 1;
|
||||
|
||||
makevectors(self.v_angle);
|
||||
traceline (self.origin, self.origin + v_forward * 600, TRUE, self);
|
||||
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
|
||||
WriteEntity (MSG_BROADCAST, self);
|
||||
WriteCoord (MSG_BROADCAST, self.origin_x);
|
||||
WriteCoord (MSG_BROADCAST, self.origin_y);
|
||||
WriteCoord (MSG_BROADCAST, self.origin_z);
|
||||
WriteCoord (MSG_BROADCAST, trace_endpos_x);
|
||||
WriteCoord (MSG_BROADCAST, trace_endpos_y);
|
||||
WriteCoord (MSG_BROADCAST, trace_endpos_z);
|
||||
|
||||
LightningDamage (self.origin, trace_endpos + v_forward * 4, self, 30);
|
||||
};
|
||||
|
||||
void() GrenadeExplode =
|
||||
{
|
||||
RadiusDamage (self, self.owner, 120, world);
|
||||
te_explosion(self.origin);
|
||||
BecomeExplosion ();
|
||||
};
|
||||
|
||||
void() GrenadeTouch =
|
||||
{
|
||||
if (pointcontents(self.origin) == CONTENT_SKY)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
if (other.takedamage == DAMAGE_AIM)
|
||||
{
|
||||
GrenadeExplode();
|
||||
return;
|
||||
}
|
||||
sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
|
||||
};
|
||||
|
||||
void() W_FireGrenade =
|
||||
{
|
||||
local entity missile;
|
||||
|
||||
self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
|
||||
|
||||
sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
|
||||
|
||||
self.punchangle_x = -2;
|
||||
|
||||
missile = spawn ();
|
||||
missile.owner = self;
|
||||
missile.movetype = MOVETYPE_BOUNCE;
|
||||
missile.solid = SOLID_BBOX;
|
||||
missile.classname = "grenade";
|
||||
|
||||
// set missile speed
|
||||
|
||||
makevectors (self.v_angle);
|
||||
missile.velocity = v_forward * 600 + crandom()*v_right*10 + crandom()*v_up*10 + '0 0 200';
|
||||
|
||||
|
||||
//if (self.v_angle_x)
|
||||
//missile.velocity = v_forward*600 + v_up*200 + crandom()*v_right*10 + crandom()*v_up*10;
|
||||
/*else
|
||||
{
|
||||
dprint("v_angle_x == 0\n");
|
||||
missile.velocity = v_forward * 600;
|
||||
missile.velocity_z = 200;
|
||||
}*/
|
||||
|
||||
missile.avelocity = '300 300 300';
|
||||
|
||||
missile.angles = vectoangles(missile.velocity);
|
||||
|
||||
missile.touch = GrenadeTouch;
|
||||
|
||||
// set missile duration
|
||||
missile.think = GrenadeExplode;
|
||||
missile.nextthink = time + 2.5;
|
||||
|
||||
setmodel (missile, "progs/grenade.mdl");
|
||||
setsize (missile, '0 0 0', '0 0 0');
|
||||
setorigin (missile, self.origin + v_forward*12 + self.view_ofs - v_up*12);
|
||||
};
|
||||
|
||||
void() spike_touch;
|
||||
void() superspike_touch;
|
||||
|
||||
void(vector org, vector dir) launch_spike =
|
||||
{
|
||||
newmis = spawn ();
|
||||
newmis.owner = self;
|
||||
newmis.movetype = MOVETYPE_FLYMISSILE;
|
||||
newmis.solid = SOLID_BBOX;
|
||||
|
||||
newmis.angles = vectoangles(dir);
|
||||
|
||||
newmis.touch = spike_touch;
|
||||
newmis.classname = "spike";
|
||||
newmis.think = SUB_Remove;
|
||||
newmis.nextthink = time + 6;
|
||||
setmodel (newmis, "progs/spike.mdl");
|
||||
setsize (newmis, [0,0,0], [0,0,0]);
|
||||
setorigin (newmis, org);
|
||||
|
||||
newmis.velocity = dir * 1000;
|
||||
};
|
||||
|
||||
void() W_FireSuperSpikes =
|
||||
{
|
||||
local vector dir;
|
||||
|
||||
sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
|
||||
self.attack_finished = time + 0.2;
|
||||
self.currentammo = self.ammo_nails = self.ammo_nails - 2;
|
||||
//dir = aim (self, 1000);
|
||||
//launch_spike (self.origin + '0 0 16', dir);
|
||||
|
||||
dir = v_forward;
|
||||
launch_spike (self.origin + v_forward * 12 + self.view_ofs - v_up * 12, dir);
|
||||
|
||||
newmis.touch = superspike_touch;
|
||||
setmodel (newmis, "progs/s_spike.mdl");
|
||||
setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
|
||||
self.punchangle_x = -2;
|
||||
};
|
||||
|
||||
void(float ox) W_FireSpikes =
|
||||
{
|
||||
local vector dir;
|
||||
|
||||
makevectors (self.v_angle);
|
||||
|
||||
if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
|
||||
{
|
||||
W_FireSuperSpikes ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.ammo_nails < 1)
|
||||
{
|
||||
self.weapon = W_BestWeapon (self);
|
||||
W_UpdateWeapon (self);
|
||||
return;
|
||||
}
|
||||
|
||||
sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
|
||||
self.attack_finished = time + 0.2;
|
||||
self.currentammo = self.ammo_nails = self.ammo_nails - 1;
|
||||
//dir = aim (self, 1000);
|
||||
//launch_spike (self.origin + '0 0 16' + v_right*ox, dir);
|
||||
|
||||
dir = v_forward;
|
||||
launch_spike (self.origin + v_forward * 8 + self.view_ofs - v_up * 12 + v_right * ox, dir);
|
||||
|
||||
|
||||
self.punchangle_x = -2;
|
||||
};
|
||||
|
||||
|
||||
|
||||
void() spike_touch =
|
||||
{
|
||||
|
||||
if (pointcontents(self.origin) == CONTENT_SKY)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
|
||||
// hit something that bleeds
|
||||
if (other.takedamage)
|
||||
{
|
||||
if (other.solid == SOLID_BSP)
|
||||
SpawnTouchParticles(9, other.colour);
|
||||
else
|
||||
SpawnTouchblood (9);
|
||||
Damage (other, self, self.owner, 9);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
|
||||
if (self.classname == "wizspike")
|
||||
WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
|
||||
else if (self.classname == "knightspike")
|
||||
WriteByte (MSG_BROADCAST, TE_KNIGHTSPIKE);
|
||||
else
|
||||
WriteByte (MSG_BROADCAST, TE_SPIKE);
|
||||
WriteCoord (MSG_BROADCAST, self.origin_x);
|
||||
WriteCoord (MSG_BROADCAST, self.origin_y);
|
||||
WriteCoord (MSG_BROADCAST, self.origin_z);
|
||||
}
|
||||
|
||||
remove(self);
|
||||
|
||||
};
|
||||
|
||||
void() superspike_touch =
|
||||
{
|
||||
if (pointcontents(self.origin) == CONTENT_SKY)
|
||||
{
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
|
||||
// hit something that bleeds
|
||||
if (other.takedamage)
|
||||
{
|
||||
if (other.solid == SOLID_BSP)
|
||||
SpawnTouchParticles(18, other.colour);
|
||||
else
|
||||
SpawnTouchblood (18);
|
||||
|
||||
Damage (other, self, self.owner, 18);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
|
||||
WriteCoord (MSG_BROADCAST, self.origin_x);
|
||||
WriteCoord (MSG_BROADCAST, self.origin_y);
|
||||
WriteCoord (MSG_BROADCAST, self.origin_z);
|
||||
}
|
||||
|
||||
remove(self);
|
||||
|
||||
};
|
||||
|
||||
/*==========
|
||||
W_Attack
|
||||
==========*/
|
||||
void() player_axe1;
|
||||
void() player_axeb1;
|
||||
void() player_axec1;
|
||||
void() player_axed1;
|
||||
void() player_shot1;
|
||||
void() player_nail;
|
||||
void() player_lightning;
|
||||
void() player_rocket1;
|
||||
void() W_Attack =
|
||||
{
|
||||
if (time < self.attack_finished)
|
||||
return;
|
||||
if (!self.weapon)
|
||||
return;
|
||||
if (!W_CheckNoAmmo(self))
|
||||
{
|
||||
self.weapon = W_BestWeapon(self);
|
||||
W_UpdateWeapon(self);
|
||||
return;
|
||||
}
|
||||
|
||||
makevectors (self.v_angle);
|
||||
self.show_hostile = time + 1;
|
||||
|
||||
if (self.weapon == IT_AXE)
|
||||
{
|
||||
sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
|
||||
float r = random();
|
||||
if (r < 0.25)
|
||||
player_axe1 ();
|
||||
else if (r<0.5)
|
||||
player_axeb1 ();
|
||||
else if (r<0.75)
|
||||
player_axec1 ();
|
||||
else
|
||||
player_axed1 ();
|
||||
self.attack_finished = time + 0.5;
|
||||
}
|
||||
else if (self.weapon == IT_SHOTGUN)
|
||||
{
|
||||
player_shot1 ();
|
||||
W_FireShotgun ();
|
||||
self.attack_finished = time + 0.5;
|
||||
}
|
||||
else if (self.weapon == IT_SUPER_SHOTGUN)
|
||||
{
|
||||
player_shot1 ();
|
||||
W_FireSuperShotgun ();
|
||||
self.attack_finished = time + 0.7;
|
||||
}
|
||||
else if (self.weapon == IT_NAILGUN)
|
||||
{
|
||||
player_nail ();
|
||||
}
|
||||
else if (self.weapon == IT_SUPER_NAILGUN)
|
||||
{
|
||||
player_nail ();
|
||||
}
|
||||
else if (self.weapon == IT_GRENADE_LAUNCHER)
|
||||
{
|
||||
player_rocket1();
|
||||
W_FireGrenade();
|
||||
self.attack_finished = time + 0.6;
|
||||
}
|
||||
else if (self.weapon == IT_ROCKET_LAUNCHER)
|
||||
{
|
||||
player_rocket1();
|
||||
W_FireRocket();
|
||||
self.attack_finished = time + 0.8;
|
||||
}
|
||||
else if (self.weapon == IT_LIGHTNING)
|
||||
{
|
||||
sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
|
||||
player_lightning();
|
||||
}
|
||||
};
|
||||
|
||||
/*==========
|
||||
W_ChangeWeapon
|
||||
==========*/
|
||||
void(float wep) W_ChangeWeapon =
|
||||
{
|
||||
float am = 0;
|
||||
float it = 0;
|
||||
if (wep == 1)
|
||||
{
|
||||
it = IT_AXE;
|
||||
}
|
||||
else if (wep == 2)
|
||||
{
|
||||
it = IT_SHOTGUN;
|
||||
if (self.ammo_shells < 1)
|
||||
am = 1;
|
||||
}
|
||||
else if (wep == 3)
|
||||
{
|
||||
it = IT_SUPER_SHOTGUN;
|
||||
if (self.ammo_shells < 2)
|
||||
am = 1;
|
||||
}
|
||||
else if (wep == 4)
|
||||
{
|
||||
it = IT_NAILGUN;
|
||||
if (self.ammo_nails < 1)
|
||||
am = 1;
|
||||
}
|
||||
else if (wep == 5)
|
||||
{
|
||||
it = IT_SUPER_NAILGUN;
|
||||
if (self.ammo_nails < 2)
|
||||
am = 1;
|
||||
}
|
||||
else if (wep == 6)
|
||||
{
|
||||
it = IT_GRENADE_LAUNCHER;
|
||||
if (self.ammo_rockets < 1)
|
||||
am = 1;
|
||||
}
|
||||
else if (wep == 7)
|
||||
{
|
||||
it = IT_ROCKET_LAUNCHER;
|
||||
if (self.ammo_rockets < 1)
|
||||
am = 1;
|
||||
}
|
||||
else if (wep == 8)
|
||||
{
|
||||
it = IT_LIGHTNING;
|
||||
if (self.ammo_cells < 1)
|
||||
am = 1;
|
||||
}
|
||||
|
||||
if (!(self.items & it))
|
||||
{
|
||||
sprint (self, "no weapon.\n");
|
||||
return;
|
||||
}
|
||||
if (am)
|
||||
{
|
||||
sprint (self, "not enough ammo.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
self.weapon = it;
|
||||
W_UpdateWeapon(self);
|
||||
};
|
||||
|
||||
/*==========
|
||||
W_Cheat
|
||||
==========*/
|
||||
void() W_Cheat =
|
||||
{
|
||||
self.ammo_rockets = 100;
|
||||
self.ammo_nails = 200;
|
||||
self.ammo_shells = 100;
|
||||
self.ammo_cells = 200;
|
||||
self.items = self.items |
|
||||
IT_AXE |
|
||||
IT_SHOTGUN |
|
||||
IT_SUPER_SHOTGUN |
|
||||
IT_NAILGUN |
|
||||
IT_SUPER_NAILGUN |
|
||||
IT_GRENADE_LAUNCHER |
|
||||
IT_ROCKET_LAUNCHER |
|
||||
IT_LIGHTNING |
|
||||
IT_KEY1 | IT_KEY2;
|
||||
|
||||
self.weapon = IT_ROCKET_LAUNCHER;
|
||||
W_UpdateWeapon(self);
|
||||
};
|
||||
|
||||
/*==========
|
||||
W_RuneCheat
|
||||
==========*/
|
||||
void() W_RuneCheat =
|
||||
{
|
||||
if (!(serverflags & 1))
|
||||
serverflags = serverflags + 1;
|
||||
else if (!(serverflags & 2))
|
||||
serverflags = serverflags + 2;
|
||||
else if (!(serverflags & 4))
|
||||
serverflags = serverflags + 4;
|
||||
else if (!(serverflags & 8))
|
||||
serverflags = serverflags + 8;
|
||||
};
|
||||
|
||||
/*==========
|
||||
QuadCheat
|
||||
==========*/
|
||||
void() W_QuadCheat =
|
||||
{
|
||||
self.super_time = 1;
|
||||
self.super_damage_finished = time + 30;
|
||||
self.items = self.items | IT_QUAD;
|
||||
sprint(self, "You got the Quad Damage\n");
|
||||
sound(self, CHAN_VOICE, "items/damage.wav", 1.0, ATTN_NORM);
|
||||
stuffcmd(self, "bf\n");
|
||||
};
|
||||
|
||||
/*==========
|
||||
PentCheat
|
||||
==========*/
|
||||
void() W_PentCheat =
|
||||
{
|
||||
self.invincible_time = 1;
|
||||
self.invincible_finished = time + 30;
|
||||
self.items = self.items | IT_INVULNERABILITY;
|
||||
sprint(self, "You got the Pentagram of Protection!\n");
|
||||
sound(self, CHAN_VOICE, "items/protect.wav", 1.0, ATTN_NORM);
|
||||
stuffcmd(self, "bf\n");
|
||||
};
|
||||
|
||||
/*==========
|
||||
RingCheat
|
||||
==========*/
|
||||
void() W_RingCheat =
|
||||
{
|
||||
self.invisible_time = 1;
|
||||
self.invisible_finished = time + 30;
|
||||
self.items = self.items | IT_INVISIBILITY;
|
||||
sprint(self, "You got the Ring of Shadows\n");
|
||||
sound(self, CHAN_VOICE, "items/inv1.wav", 1.0, ATTN_NORM);
|
||||
stuffcmd(self, "bf\n");
|
||||
};
|
||||
|
||||
/*==========
|
||||
SuitCheat
|
||||
==========*/
|
||||
void() W_SuitCheat =
|
||||
{
|
||||
self.rad_time = 1;
|
||||
self.radsuit_finished = time + 30;
|
||||
self.items = self.items | IT_SUIT;
|
||||
sprint(self, "You got the Biosuit\n");
|
||||
sound(self, CHAN_VOICE, "items/suit.wav", 1.0, ATTN_NORM);
|
||||
stuffcmd(self, "bf\n");
|
||||
};
|
||||
|
||||
/*==========
|
||||
W_ImpulseCommands
|
||||
==========*/
|
||||
void() W_ImpulseCommands =
|
||||
{
|
||||
if (!(deathmatch || coop))
|
||||
{
|
||||
if (self.impulse == 9)
|
||||
W_Cheat();
|
||||
if (self.impulse == 11)
|
||||
W_RuneCheat();
|
||||
if (self.impulse == 255)
|
||||
W_QuadCheat();
|
||||
if (self.impulse == 254)
|
||||
W_PentCheat();
|
||||
if (self.impulse == 253)
|
||||
W_RingCheat();
|
||||
if (self.impulse == 252)
|
||||
W_SuitCheat();
|
||||
}
|
||||
|
||||
if (time < self.attack_finished)
|
||||
return;
|
||||
if (self.impulse >= 1 && self.impulse <= 8)
|
||||
W_ChangeWeapon(self.impulse);
|
||||
self.impulse = 0;
|
||||
};
|
||||
|
||||
/*==========
|
||||
W_QuadDamageSound
|
||||
==========*/
|
||||
void() W_QuadDamageSound =
|
||||
{
|
||||
if (self.items & IT_QUAD)
|
||||
{
|
||||
if (self.super_sound < time)
|
||||
{
|
||||
self.super_sound = time + 1;
|
||||
sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*==========
|
||||
W_WeaponFrame
|
||||
==========*/
|
||||
void() W_WeaponFrame =
|
||||
{
|
||||
W_ImpulseCommands();
|
||||
|
||||
if (self.button0)
|
||||
{
|
||||
W_QuadDamageSound();
|
||||
W_Attack();
|
||||
}
|
||||
};
|
||||
218
mod_slipgate/source/server/world.qc
Normal file
218
mod_slipgate/source/server/world.qc
Normal file
@@ -0,0 +1,218 @@
|
||||
/*========================================
|
||||
world.qc
|
||||
========================================*/
|
||||
|
||||
/*==========
|
||||
main
|
||||
==========*/
|
||||
void() main = {};
|
||||
|
||||
/*==========
|
||||
setup_gravity
|
||||
==========*/
|
||||
void() setup_gravity =
|
||||
{
|
||||
// custom map gravity
|
||||
if (mapname == "e1m8")
|
||||
cvar_set ("sv_gravity", "100");
|
||||
else if (self.gravity)
|
||||
cvar_set ("sv_gravity", ftos(self.gravity));
|
||||
else
|
||||
cvar_set ("sv_gravity", "800");
|
||||
|
||||
sv_gravity = cvar("sv_gravity");
|
||||
};
|
||||
|
||||
/*==========
|
||||
precache_sounds
|
||||
==========*/
|
||||
void() precache_sounds =
|
||||
{
|
||||
// sounds used from C code
|
||||
precache_sound ("demon/dland2.wav"); // landing thud
|
||||
precache_sound ("misc/h2ohit1.wav"); // landing splash
|
||||
precache_sound ("misc/talk.wav"); // chat
|
||||
precache_sound ("weapons/r_exp3.wav"); // explosion
|
||||
precache_sound ("weapons/ric1.wav"); // spike ricochet
|
||||
precache_sound ("weapons/ric2.wav"); // spike ricochet
|
||||
precache_sound ("weapons/ric3.wav"); // spike ricochet
|
||||
precache_sound ("weapons/tink1.wav"); // spike tink
|
||||
precache_sound ("wizard/hit.wav"); // scrag projectile impact
|
||||
precache_sound ("hknight/hit.wav"); // death knight projectile impact
|
||||
|
||||
// player movement sounds
|
||||
precache_sound ("player/plyrjmp8.wav"); // player jump
|
||||
precache_sound ("player/land.wav"); // player landing
|
||||
precache_sound ("player/land2.wav"); // player hurt landing
|
||||
precache_sound ("player/ladder1.wav");
|
||||
precache_sound ("player/ladder2.wav");
|
||||
precache_sound ("player/ladder3.wav");
|
||||
precache_sound ("player/ladder4.wav");
|
||||
precache_sound ("player/ladder5.wav");
|
||||
|
||||
// player pain sounds
|
||||
precache_sound ("player/pain1.wav");
|
||||
precache_sound ("player/pain2.wav");
|
||||
precache_sound ("player/pain3.wav");
|
||||
precache_sound ("player/pain4.wav");
|
||||
precache_sound ("player/pain5.wav");
|
||||
precache_sound ("player/pain6.wav");
|
||||
|
||||
// player death sounds
|
||||
precache_sound ("player/death1.wav");
|
||||
precache_sound ("player/death2.wav");
|
||||
precache_sound ("player/death3.wav");
|
||||
precache_sound ("player/death4.wav");
|
||||
precache_sound ("player/death5.wav");
|
||||
|
||||
// gib sounds
|
||||
precache_sound ("player/gib.wav");
|
||||
precache_sound ("player/udeath.wav");
|
||||
precache_sound ("player/tornoff2.wav");
|
||||
precache_sound ("player/teledth1.wav");
|
||||
precache_sound ("zombie/z_miss.wav");
|
||||
|
||||
// player liquid sounds
|
||||
precache_sound ("player/h2ojump.wav"); // jumping into water
|
||||
precache_sound ("player/inh2o.wav"); // enter water
|
||||
precache_sound ("player/slimbrn2.wav"); // enter slime
|
||||
precache_sound ("player/inlava.wav"); // enter lava
|
||||
precache_sound ("misc/outwater.wav"); // leaving water
|
||||
precache_sound ("player/lburn1.wav"); // lava burn
|
||||
precache_sound ("player/lburn2.wav"); // lava burn
|
||||
precache_sound ("misc/water1.wav"); // swimming
|
||||
precache_sound ("misc/water2.wav"); // swimming
|
||||
precache_sound ("player/drown1.wav"); // drowning pain
|
||||
precache_sound ("player/drown2.wav"); // drowning pain
|
||||
precache_sound ("player/gasp1.wav"); // gasping for air
|
||||
precache_sound ("player/gasp2.wav"); // taking breath
|
||||
precache_sound ("player/h2odeath.wav"); // drowning death
|
||||
|
||||
// teleport sounds
|
||||
precache_sound ("misc/r_tele1.wav");
|
||||
precache_sound ("misc/r_tele2.wav");
|
||||
precache_sound ("misc/r_tele3.wav");
|
||||
precache_sound ("misc/r_tele4.wav");
|
||||
precache_sound ("misc/r_tele5.wav");
|
||||
|
||||
// items
|
||||
precache_sound ("items/itembk2.wav"); // item respawn
|
||||
precache_sound ("weapons/lock4.wav"); // ammo pick up
|
||||
precache_sound ("weapons/pkup.wav"); // weapon pick up
|
||||
precache_sound ("items/armor1.wav"); // armor pick up
|
||||
// pentagram of protection
|
||||
precache_sound ("items/protect.wav");
|
||||
precache_sound ("items/protect2.wav");
|
||||
precache_sound ("items/protect3.wav");
|
||||
// biosuit
|
||||
precache_sound ("items/suit.wav");
|
||||
precache_sound ("items/suit2.wav");
|
||||
// ring of shadows
|
||||
precache_sound ("items/inv1.wav");
|
||||
precache_sound ("items/inv2.wav");
|
||||
precache_sound ("items/inv3.wav");
|
||||
// quad damage
|
||||
precache_sound ("items/damage.wav");
|
||||
precache_sound ("items/damage2.wav");
|
||||
precache_sound ("items/damage3.wav");
|
||||
|
||||
// weapon sounds
|
||||
precache_sound ("weapons/ax1.wav"); // axe swoosh
|
||||
precache_sound ("player/axhit1.wav"); // axe hit meat
|
||||
precache_sound ("player/axhit2.wav"); // axe hit world
|
||||
precache_sound ("weapons/guncock.wav"); // shotgun
|
||||
precache_sound ("weapons/shotgn2.wav"); // super shotgun
|
||||
precache_sound ("weapons/rocket1i.wav"); // nailgun
|
||||
precache_sound ("weapons/spike2.wav"); // super nailgun
|
||||
precache_sound ("weapons/grenade.wav"); // grenade launcher
|
||||
precache_sound ("weapons/bounce.wav"); // grenade bounce
|
||||
precache_sound ("weapons/sgun1.wav"); // rocket launcher
|
||||
precache_sound ("weapons/lstart.wav"); // thunderbolt start
|
||||
precache_sound ("weapons/lhit.wav"); // thunderbolt
|
||||
};
|
||||
|
||||
/*==========
|
||||
precache_models
|
||||
==========*/
|
||||
void() precache_models =
|
||||
{
|
||||
// player models
|
||||
precache_model ("progs/player.mdl");
|
||||
precache_model ("progs/h_player.mdl");
|
||||
precache_model ("progs/eyes.mdl");
|
||||
|
||||
// gore
|
||||
precache_model ("progs/zom_gib.mdl");
|
||||
precache_model ("progs/gib1.mdl");
|
||||
precache_model ("progs/gib2.mdl");
|
||||
precache_model ("progs/gib3.mdl");
|
||||
precache_model ("progs/gib4.mdl");
|
||||
precache_model ("progs/gib5.mdl");
|
||||
precache_model ("progs/blood.mdl");
|
||||
|
||||
// sprites
|
||||
precache_model ("progs/s_bubble.spr");
|
||||
precache_model ("progs/s_explod.spr");
|
||||
precache_model ("progs/s_null.spr");
|
||||
|
||||
// weapon models
|
||||
precache_model ("progs/v_axe.mdl");
|
||||
precache_model ("progs/v_shot.mdl");
|
||||
precache_model ("progs/v_nail.mdl");
|
||||
precache_model ("progs/v_rock.mdl");
|
||||
precache_model ("progs/v_shot2.mdl");
|
||||
precache_model ("progs/v_nail2.mdl");
|
||||
precache_model ("progs/v_rock2.mdl");
|
||||
precache_model ("progs/v_light.mdl");
|
||||
|
||||
// projectiles, etc
|
||||
precache_model ("progs/bolt.mdl");
|
||||
precache_model ("progs/bolt2.mdl");
|
||||
precache_model ("progs/bolt3.mdl");
|
||||
precache_model ("progs/beam.mdl");
|
||||
precache_model ("progs/missile.mdl");
|
||||
precache_model ("progs/grenade.mdl");
|
||||
precache_model ("progs/spike.mdl");
|
||||
precache_model ("progs/s_spike.mdl");
|
||||
precache_model ("progs/backpack.mdl");
|
||||
precache_model ("progs/smoke.mdl");
|
||||
};
|
||||
|
||||
/*QUAKED worldspawn (0 0 0) ?
|
||||
The world entity.
|
||||
|
||||
Keys:
|
||||
"message" "name" - Map name
|
||||
"sounds" "n" - CD / Music track to play
|
||||
"worldtype" "n":
|
||||
0 - medieval, 1 - metal, 2 - base
|
||||
*/
|
||||
void() worldspawn =
|
||||
{
|
||||
// fix skill at map start
|
||||
skill = rint(cvar("skill"));
|
||||
if (skill < 0)
|
||||
skill = 0;
|
||||
if (skill > 3)
|
||||
skill = 3;
|
||||
|
||||
precache_sounds();
|
||||
precache_models();
|
||||
setup_lightstyles();
|
||||
setup_gravity();
|
||||
InitBodyQue();
|
||||
WaypointInit();
|
||||
};
|
||||
|
||||
/*==========
|
||||
StartFrame
|
||||
==========*/
|
||||
void() StartFrame =
|
||||
{
|
||||
framecount = framecount + 1;
|
||||
|
||||
teamplay = cvar("teamplay");
|
||||
developer = cvar("developer");
|
||||
|
||||
WaypointFrame();
|
||||
};
|
||||
Reference in New Issue
Block a user