Git Repos / fte_dogmode / commit e134091
Commit: e134091dd10c4c29e67852ee5f03b16dceca3658
Parent: dcb9d642dd88b7f9ab33596a717431f332cdbb16
Author: Cameron Vanderzanden, 2024-02-18 18:28
Committer: Cameron Vanderzanden, 2024-02-18 18:28
Commit Message
Client/player, projectiles, entrypoints refactor I have once gain forgotten where this commit started and what all it includes. The major points of interest are: client handling and the player entity have been folded together as a base class, the server entriypoints have been refactored (again), and the projectile system and related monster & player attacks have been refactored. There are definitely regressions in this commit. Projectile code sometimes tries to remove and already freed entity, some projectiles (ones with custom physics) sometimes pass through monsters, sometimes rottweiler heads bark at and chase the player, et cetera. (That last one I've only seen once). In other words: beware of bugs. All projectiles *except* bullets have been refactored. I'm committing now, before doing bullets, because I may implement an AD-like system of projectile (non-hitscan) bullets. Several projectiles have an experimental .customphysics function that disregards normal MINS and MAXS (bounding box) when moving through the world. This in turn allows them to have a different bbox for collision testing *against* them. The use case for this is to allow the player (or monsters) to shoot explosive projectiles out of the sky. Ever wished you could shoot a voreball to destroy it? Now you can. It is, unfortunately, slow and a little buggy. Something to improve on. See the class base_projectile_qcphys in qc/base_projectiles.qc for the code. Almost the entire program has been refactored into object-oriented Quake C now (aside from a few stray systems like cutscenes and gibs). I should now be able to focus on bugfixing and improvements (well, changes) to game systems.
Change List
Diff qc/ai.qc
diff --git a/qc/ai.qc b/qc/ai.qc
deleted file mode 100644
index 776c1a1..0000000
--- a/qc/ai.qc
+++ /dev/null
@@ -1,838 +0,0 @@
-/*
-float NO_SIGHT_SOUND = 32;
-float PASSIVE_UNTIL_ATTACKED = 64;
-float PASSIVE_ALWAYS = 128;
-*/
-
-/*
-
-.enemy
-Will be world if not currently angry at anyone.
-
-.movetarget
-The next path spot to walk toward. If .enemy, ignore .movetarget.
-When an enemy is killed, the monster will try to return to it's path.
-
-.huntt_ime
-Set to time + something when the player is in sight, but movement straight for
-him is blocked. This causes the monster to use wall following code for
-movement direction instead of sighting on the player.
-
-.ideal_yaw
-A yaw angle of the intended direction, which will be turned towards at up
-to 45 deg / state. If the enemy is in view and hunt_time is not active,
-this will be the exact line towards the enemy.
-
-.pausetime
-A monster will leave it's stand state and head towards it's .movetarget when
-time > .pausetime.
-
-walkmove(angle, speed) primitive is all or nothing
-*/
-
-
-//
-// globals
-//
-
-//
-// when a monster becomes angry at a player, that monster will be used
-// as the sight target the next frame so that monsters near that one
-// will wake up even if they wouldn't have noticed the player
-//
-/*
-entity sight_entity;
-float sight_entity_time;
-*/
-
-/*
-==============================================================================
-
-MOVETARGET CODE
-
-The angle of the movetarget effects standing and bowing direction, but has no effect on movement, which always heads to the next target.
-
-targetname
-must be present. The name of this movetarget.
-
-target
-the next spot to move to. If not present, stop here for good.
-
-pausetime
-The number of seconds to spend standing or bowing for path_stand or path_bow
-
-==============================================================================
-*/
-
-
-void() movetarget_f =
-{
- if (!self.targetname)
- objerror ("monster_movetarget: no targetname");
-
- self.solid = SOLID_TRIGGER;
- self.touch = t_movetarget;
- setsize (self, '-8 -8 -8', '8 8 8');
-
-};
-
-/*
-=============
-t_movetarget
-
-Something has bumped into a movetarget. If it is a monster
-moving towards it, change the next destination and continue.
-==============
-*/
-void() t_movetarget =
-{
-local entity temp;
-
- if (other.movetarget != self)
- return;
-
- if (other.enemy)
- return; // fighting, not following a path
-
- temp = self;
- self = other;
- other = temp;
-
- if (self.classname == "monster_ogre")
- sound_misc (self, CHAN_VOICE, "ogre/ogdrag.wav", 1, ATTN_IDLE);// play chainsaw drag sound -- sound_custom -- dumptruck_ds
-
-//dprint ("t_movetarget\n");
- self.goalentity = self.movetarget = find (world, targetname, other.target);
- self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
- if (!self.movetarget)
- {
- self.pausetime = time + 999999;
- self.th_stand ();
- return;
- }
-};
-
-
-
-//============================================================================
-
-/*
-=============
-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 =
-{
- local vector spot1 = self.origin + self.view_ofs;
- local vector spot2 = targ.origin + targ.view_ofs;
- local float r = vlen (spot1 - spot2);
-
- if (r < 120)
- return RANGE_MELEE;
- if (r < 500)
- return RANGE_NEAR;
- if (r < 1000)
- return RANGE_MID;
- return RANGE_FAR;
-};
-
-/*
-=============
-visible
-
-returns 1 if the entity is visible to self, even if not infront ()
-=============
-*/
-float (entity targ) visible =
-{
- local vector spot1, spot2;
-
- spot1 = self.origin + self.view_ofs;
- spot2 = targ.origin + targ.view_ofs;
- traceline (spot1, spot2, TRUE, self); // see through other monsters
-
- if (trace_inopen && trace_inwater)
- return FALSE; // sight line crossed contents
-
- 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 =
-{
- local vector vec;
- local float dot;
-
- makevectors (self.angles);
- vec = normalize (targ.origin - self.origin);
- dot = vec * v_forward;
-
- if ( dot > 0.3)
- {
- return TRUE;
- }
- return FALSE;
-};
-
-
-//============================================================================
-
-/*
-===========
-ChangeYaw
-
-Turns towards self.ideal_yaw at self.yaw_speed
-Sets the global variable current_yaw
-Called every 0.1 sec by monsters
-============
-*/
-/*
-
-void() ChangeYaw =
-{
- local float ideal, move;
-
-//current_yaw = self.ideal_yaw;
-// mod down the current angle
- current_yaw = anglemod( self.angles_y );
- ideal = self.ideal_yaw;
-
- if (current_yaw == ideal)
- return;
-
- move = ideal - current_yaw;
- if (ideal > current_yaw)
- {
- if (move > 180)
- move = move - 360;
- }
- else
- {
- if (move < -180)
- move = move + 360;
- }
-
- if (move > 0)
- {
- if (move > self.yaw_speed)
- move = self.yaw_speed;
- }
- else
- {
- if (move < 0-self.yaw_speed )
- move = 0-self.yaw_speed;
- }
-
- current_yaw = anglemod (current_yaw + move);
-
- self.angles_y = current_yaw;
-};
-
-*/
-
-
-//============================================================================
-
-/*
-void() HuntTarget =
-{
- self.goalentity = self.enemy;
- self.think = self.th_run;
- self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
- self.nextthink = time + 0.1;
- SUB_AttackFinished (1); // wait a while before first attack
-};
-
-void() SightSound =
-{
- if !(self.spawnflags & PASSIVE_ALWAYS)
-
- local float rsnd;
-
- if (self.classname == "monster_ogre")
- sound_sight (self, CHAN_VOICE, "ogre/ogwake.wav", 1, ATTN_NORM);
- else if (self.classname == "monster_ogre_marksman")
- sound_sight (self, CHAN_VOICE, "ogre/ogwake.wav", 1, ATTN_NORM);
- else if (self.classname == "monster_knight")
- sound_sight (self, CHAN_VOICE, "knight/ksight.wav", 1, ATTN_NORM);
- else if (self.classname == "monster_shambler")
- sound_sight (self, CHAN_VOICE, "shambler/ssight.wav", 1, ATTN_NORM);
- else if (self.classname == "monster_demon1")
- sound_sight (self, CHAN_VOICE, "demon/sight2.wav", 1, ATTN_NORM);
- else if (self.classname == "monster_wizard")
- sound_sight (self, CHAN_VOICE, "wizard/wsight.wav", 1, ATTN_NORM);
- else if (self.classname == "monster_zombie")
- sound_sight (self, CHAN_VOICE, "zombie/z_idle.wav", 1, ATTN_NORM);
- else if (self.classname == "monster_dog")
- sound_sight (self, CHAN_VOICE, "dog/dsight.wav", 1, ATTN_NORM); //dumptruck_ds
- else if (self.classname == "monster_hell_knight")
- sound_sight (self, CHAN_VOICE, "hknight/sight1.wav", 1, ATTN_NORM);
- else if (self.classname == "monster_enforcer")
- {
- rsnd = rint(random() * 3);
- if (rsnd == 1)
- sound_sight (self, CHAN_VOICE, "enforcer/sight1.wav", 1, ATTN_NORM); //dumptruck_ds
- else if (rsnd == 2)
- sound_misc (self, CHAN_VOICE, "enforcer/sight2.wav", 1, ATTN_NORM);
- else if (rsnd == 0)
- sound_misc1 (self, CHAN_VOICE, "enforcer/sight3.wav", 1, ATTN_NORM);
- else
- sound_misc2 (self, CHAN_VOICE, "enforcer/sight4.wav", 1, ATTN_NORM);
- }
- else if (self.classname == "monster_army")
- sound_sight (self, CHAN_VOICE, "soldier/sight1.wav", 1, ATTN_NORM);
- else if (self.classname == "monster_shalrath")
- sound_sight (self, CHAN_VOICE, "shalrath/sight.wav", 1, ATTN_NORM);
- else if (self.classname == "monster_oldone2") //dumptruck_ds added Shub sighting SFX
- sound_sight (self, CHAN_VOICE, "boss2/sight.wav", 1, ATTN_NONE);
-};
-
-// TODO CEV
-void(entity ent) FoundTargetForEntity =
-{
- entity oself = self;
- self = ent;
- FoundTarget ();
- self = oself;
-}
-
-void() FoundTarget =
-{
- if (self.enemy.classname == "player")
- { // let other monsters see this monster for a while
- sight_entity = self;
- sight_entity_time = time;
- }
-
- self.show_hostile = time + 1; // wake up other monsters
-
- if !(self.spawnflags & NO_SIGHT_SOUND || self.spawnflags & PASSIVE_ALWAYS || self.spawnflags & PASSIVE_UNTIL_ATTACKED)
- {
- SightSound ();
- }
- HuntTarget ();
-
- if (self.sight_trigger == 1) //thanks RennyC -- dumptruck_ds
- {
- activator = self.enemy;
- SUB_UseAndForgetTargets ();
- }
-};
-*/
-
-/*
-===========
-FindTarget
-
-Self is currently not attacking anything, so try to find a target
-
-Returns TRUE if an enemy was sighted
-
-When a player fires a missile, the point of impact becomes a fakeplayer so
-that monsters that see the impact will respond as if they had seen the
-player.
-
-To avoid spending too much time, only a single client (or fakeclient) is
-checked each frame. This means multi player games will have slightly
-slower noticing monsters.
-============
-*/
-float() FindTarget =
-{
- local entity client;
- local float r;
-
- // if the first spawnflag bit is set, the monster will only
- // wake up on really seeing the player, not another monster
- // getting angry
-
- // spawnflags & 3 is a big hack, because zombie crucified
- // used the first spawn flag prior to the ambush flag, and
- // I forgot about it, so the second spawn flag works as well
- if (sight_entity_time >= time - 0.1 && !(self.spawnflags & 3))
- {
- client = sight_entity;
- if (client.enemy == self.enemy)
- return TRUE;
- }
- else
- {
- client = checkclient ();
- if (!client)
- // current check entity isn't in PVS
- return FALSE;
- }
-
- if ((self.spawnflags & PASSIVE_UNTIL_ATTACKED) ||
- (self.spawnflags & PASSIVE_ALWAYS))
- {
- return FALSE;
- }
-
- // from Copper -- dumptruck_ds
- if (client.flags & FL_NOTARGET || client.movetype == MOVETYPE_NOCLIP)
- return FALSE;
-
- if (client.health <= 0)
- return FALSE;
-
- if (client.classname != "player")
- if (client.enemy.health <= 0)
- return FALSE;
-
- if (client == self.enemy)
- return FALSE;
-
- if (client.flags & FL_NOTARGET)
- return FALSE;
- if (client.items & IT_INVISIBILITY)
- return FALSE;
-
- 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 ( /* client.show_hostile < time || */ !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;
-};
-
-
-//=============================================================================
-
-void(float dist) ai_forward =
-{
- // dprint("ai_forward\n");
- walkmove (self.angles_y, dist);
-};
-
-void(float dist) ai_back =
-{
- // dprint("ai_back\n");
- walkmove ((self.angles_y + 180), dist);
-};
-
-
-/*
-=============
-ai_pain
-
-stagger back a bit
-=============
-*/
-void(float dist) ai_pain =
-{
-
- ai_back (dist);
-/*
- local float away;
-
- away = anglemod (vectoyaw (self.origin - self.enemy.origin)
- + 180*(random()- 0.5) );
-
- walkmove (away, dist);
-*/
-};
-
-/*
-=============
-ai_painforward
-
-stagger back a bit
-=============
-*/
-void(float dist) ai_painforward =
-{
- // dprint("ai_painforward\n");
- walkmove (self.ideal_yaw, dist);
-};
-
-/*
-=============
-ai_walk
-
-The monster is walking it's beat
-=============
-*/
-void(float dist) ai_walk =
-{
-
- movedist = dist;
-
- if (self.classname == "monster_dragon")
- {
- movetogoal (dist);
- return;
- }
- // check for noticing a player
- if (FindTarget ())
- return;
-
- movetogoal (dist);
-};
-
-
-/*
-=============
-ai_stand
-
-The monster is staying in one place for a while, with slight angle turns
-=============
-*/
-void() ai_stand =
-{
- if (FindTarget ())
- return;
-
- if (time > self.pausetime)
- {
- self.th_walk ();
- return;
- }
-
-// change angle slightly
-
-};
-
-/*
-=============
-ai_turn
-
-don't move, but turn towards ideal_yaw
-=============
-*/
-void() ai_turn =
-{
- if (FindTarget ())
- return;
-
- ChangeYaw ();
-};
-
-//=============================================================================
-
-/*
-=============
-ChooseTurn
-=============
-*/
-void(vector dest3) ChooseTurn =
-{
- local vector dir, newdir;
-
- dir = self.origin - dest3;
-
- newdir_x = trace_plane_normal_y;
- newdir_y = 0 - trace_plane_normal_x;
- newdir_z = 0;
-
- if (dir * newdir > 0)
- {
- dir_x = 0 - trace_plane_normal_y;
- dir_y = trace_plane_normal_x;
- }
- else
- {
- dir_x = trace_plane_normal_y;
- dir_y = 0 - trace_plane_normal_x;
- }
-
- dir_z = 0;
- self.ideal_yaw = vectoyaw(dir);
-};
-
-/*
-============
-FacingIdeal
-
-============
-*/
-float() FacingIdeal =
-{
- local float delta;
-
- delta = anglemod(self.angles_y - self.ideal_yaw);
- if (delta > 45 && delta < 315)
- return FALSE;
- return TRUE;
-};
-
-
-//=============================================================================
-
-float() CheckAnyAttack =
-{
- if (cutscene) // Drake devkit -- dumptruck_ds
- if (self.enemy.classname == "camera")
- return FALSE; // Don't attack the camera (player)!
-
- if (!enemy_vis)
- return FALSE;
- /*
- if (self.classname == "monster_army")
- return SoldierCheckAttack ();
- */
- if ((self.classname == "monster_ogre") || (self.classname == "monster_ogre_marksman"))
- return OgreCheckAttack ();
- /*
- 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 and close until within an angle to launch a melee attack
-=============
-*/
-void() ai_run_melee =
-{
- self.ideal_yaw = enemy_yaw;
- ChangeYaw ();
-
- if (FacingIdeal())
- {
- self.th_melee ();
- self.attack_state = AS_STRAIGHT;
- }
-};
-
-
-/*
-=============
-ai_run_missile
-
-Turn in place until within an angle to launch a missile attack
-=============
-*/
-void() ai_run_missile =
-{
- self.ideal_yaw = enemy_yaw;
- // dprint("ai_run_missile GO\n");
- ChangeYaw ();
- if (FacingIdeal())
- {
- if (self.spawnflags & I_AM_TURRET)
- {
- self.th_turret();
- // dprint("th_turret...\n");
- }
- else
- {
- self.th_missile ();
- // dprint("th_missile\n");
- }
- self.attack_state = AS_STRAIGHT;
- }
-};
-
-
-/*
-=============
-ai_run_slide
-
-Strafe sideways, but stay at aproximately the same range
-=============
-*/
-void() ai_run_slide =
-{
- local float ofs;
-
- self.ideal_yaw = enemy_yaw;
- ChangeYaw ();
- if (self.lefty)
- ofs = 90;
- else
- ofs = -90;
-
- if (walkmove (self.ideal_yaw + ofs, movedist))
- return;
-
- self.lefty = 1 - self.lefty;
-
- walkmove (self.ideal_yaw - ofs, movedist);
-};
-
-
-/*
-=============
-ai_run
-
-The monster has an enemy it is trying to kill
-=============
-*/
-void(float dist) ai_run =
-{
- // dprint("ai_run\n");
- movedist = dist;
-// see if the enemy is dead
- if ((self.enemy.health <= 0) || (self.spawnflags & PASSIVE_ALWAYS))
- {
- self.enemy = world;
- // FIXME: look all around for other targets
- if (self.oldenemy.health > 0)
- {
- self.enemy = self.oldenemy;
- HuntTarget ();
- }
- else
- {
- if (self.spawnflags & I_AM_TURRET)
- {
- self.th_stand ();
- }
- else if (self.movetarget)
- self.th_walk ();
- else
- self.th_stand ();
- return;
- }
- }
-
- self.show_hostile = time + 1; // wake up other monsters
-
-// check knowledge of enemy
- enemy_vis = visible(self.enemy);
- if (enemy_vis)
- self.search_time = time + 5;
-
-// look for other coop players
- if (coop && self.search_time < time)
- {
- if (FindTarget ())
- return;
- }
-
- enemy_infront = infront(self.enemy);
- enemy_range = range(self.enemy);
- enemy_yaw = vectoyaw(self.enemy.origin - self.origin);
-
- if (self.spawnflags & I_AM_TURRET)
- {
- ai_face ();
- }
-
- // if ((self.attack_state == AS_MISSILE) || !(self.spawnflags & I_AM_TURRET))
- if (self.attack_state == AS_MISSILE)
- {
- // dprint ("ai_run_missile... from ai_run\n");
- ai_run_missile ();
- return;
- }
- // if ((self.attack_state == AS_MELEE) || !(self.spawnflags & I_AM_TURRET))
- if (self.attack_state == AS_MELEE)
- {
-//dprint ("ai_run_melee\n");
- ai_run_melee ();
- return;
- }
-
- if (CheckAnyAttack ())
- return; // beginning an attack
-
- // if ((self.attack_state == AS_SLIDING) || !(self.spawnflags & I_AM_TURRET))
- if (self.attack_state == AS_SLIDING)
- {
- ai_run_slide ();
- return;
- }
- // part of monster face from TheSolipsist
- // urged to change positions
- if (time < self.t_length) // if orientation is forced
- {
- ChangeYaw();
-
- if (walkmove(self.ideal_yaw, dist))
- return;
-
- self.ideal_yaw += 30; // dodge left
- ChangeYaw();
-
- if (walkmove(self.ideal_yaw, dist))
- return;
-
- self.ideal_yaw -= 60; // dodge right
- ChangeYaw();
- ChangeYaw();
-
- if (walkmove(self.ideal_yaw, dist))
- return;
-
- self.ideal_yaw += 30; // give up
- ChangeYaw();
- self.touch_time = self.touch_time - 0.1; // lose patience
-
- return;
- }
-
-if !(self.spawnflags & I_AM_TURRET) // keeps monster from moving to player - dumptruck_ds
-// head straight in
- movetogoal (dist); // done in C code...
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Return to the top of this page or return to the overview of this repo.
Diff qc/base_entities.qc
diff --git a/qc/base_entities.qc b/qc/base_entities.qc
index 8209813..af2a8cf 100644
--- a/qc/base_entities.qc
+++ b/qc/base_entities.qc
@@ -34,145 +34,474 @@ class base_entity: entity
float interaction_flags;
//==============================================================
- // Subs
+ // Damage Functions
//==============================================================
//--------------------------------------------------------------
- // was CheckValidTouch(); needed for both spawnable map entities
- // and temporary entities -- CEV
+ // CanDamage
+ // Returns true if the source (inflictor) can directly damage
+ // the destinatino (target). Used for explosions and melee attacks.
//--------------------------------------------------------------
- nonvirtual float(entity toucher) sub_checkvalidtouch =
+ nonvirtual float(entity src, entity dest) can_damage =
{
- if (toucher.classtype != CT_PLAYER)
- return FALSE;
- if (toucher.health <= 0)
- return FALSE;
- if (toucher.movetype == MOVETYPE_NOCLIP)
- return FALSE;
- if (this.estate != STATE_ACTIVE)
+ // bmodels need special checking because their origin is 0,0,0
+ if (dest.movetype == MOVETYPE_PUSH)
+ {
+ traceline (src.origin,
+ 0.5 * (dest.absmin + dest.absmax), TRUE, this);
+ if (trace_fraction == 1)
+ return TRUE;
+ if (trace_ent == dest)
+ return TRUE;
return FALSE;
- return TRUE;
- };
+ }
- //==============================================================
- // Interfacing
- //==============================================================
+ traceline (src.origin, dest.origin, TRUE, this);
+ if (trace_fraction == 1)
+ return TRUE;
+ traceline (src.origin, dest.origin + '15 15 0', TRUE, this);
+ if (trace_fraction == 1)
+ return TRUE;
+ traceline (src.origin, dest.origin + '-15 -15 0', TRUE, this);
+ if (trace_fraction == 1)
+ return TRUE;
+ traceline (src.origin, dest.origin + '-15 15 0', TRUE, this);
+ if (trace_fraction == 1)
+ return TRUE;
+ traceline (src.origin, dest.origin + '15 -15 0', TRUE, this);
+ if (trace_fraction == 1)
+ return TRUE;
- // blocked() seems to only be used by func_ entities so it's
- // undefined here & defined later in the base_func class -- CEV
+ return FALSE;
+ };
//--------------------------------------------------------------
- virtual void() do_think = { };
-
+ // T_RadiusDamage
//--------------------------------------------------------------
- virtual void() think =
+ nonvirtual void(entity inflictor, entity attacker, float damage,
+ entity ignore) t_radiusdamage2 =
{
- // has think been disabled? -- CEV
- if (this.interaction_flags & DISABLE_THINK)
- return;
+ local float points;
+ local entity head;
+ local vector org;
- do_think ();
+ head = findradius (inflictor.origin, damage + 40);
+
+ while (head)
+ {
+ if (head == ignore || !head.takedamage)
+ {
+ head = head.chain;
+ continue;
+ }
+
+ org = head.origin + (head.mins + head.maxs)*0.5;
+ points = 0.5 * vlen (inflictor.origin - org);
+ if (points < 0)
+ points = 0;
+ points = damage - points;
+ if (head == attacker)
+ points = points * 0.5;
+ if (points > 0)
+ {
+ if (this.can_damage (inflictor, head))
+ {
+ // shambler takes half damage from
+ // all explosions
+ if (head.classtype ==
+ CT_MONSTER_SHAMBLER)
+ {
+ this.t_damage2 (head, inflictor,
+ attacker, points * 0.5);
+ }
+ else
+ {
+ this.t_damage2 (head, inflictor,
+ attacker, points);
+ }
+ }
+ }
+ head = head.chain;
+ }
};
//--------------------------------------------------------------
- virtual void(entity toucher) do_touch = { };
-
+ // T_BeamDamage
//--------------------------------------------------------------
- virtual void() touch =
+ nonvirtual void(entity attacker, float damage) t_beamdamage2 =
{
- // has touch been disabled? -- CEV
- if (this.interaction_flags & DISABLE_TOUCH)
- return;
+ local float points;
+ local entity head;
- do_touch (other);
+ head = findradius (attacker.origin, damage + 40);
+
+ while (head)
+ {
+ if (!head.takedamage)
+ {
+ head = head.chain;
+ continue;
+ }
+
+ points = 0.5 * vlen ( attacker.origin - head.origin);
+ if (points < 0)
+ points = 0;
+ points = damage - points;
+ if (head == attacker)
+ points = points * 0.5;
+ if (points > 0)
+ {
+ if (this.can_damage (attacker, head))
+ {
+ if (head.classtype ==
+ CT_MONSTER_SHAMBLER)
+ {
+ this.t_damage2 (head, attacker,
+ attacker, points * 0.5);
+ }
+ else
+ {
+ this.t_damage2 (head, attacker,
+ attacker, points);
+ }
+ }
+ }
+ head = head.chain;
+ }
};
//--------------------------------------------------------------
- virtual void(entity caller) do_use = { };
-
+ // T_Damage
+ // The damage is coming from inflictor, but get mad at attacker
+ // This should be the only function that ever reduces health.
//--------------------------------------------------------------
- virtual void() use =
+ static void(entity targ, entity inflictor, entity attacker,
+ float damage) t_damage2 =
{
- // has use been disabled? -- CEV
- if (this.interaction_flags & DISABLE_USE)
+ // don't try to damage the world. Not healthy - bmFbr
+ if (!targ)
return;
- do_use (other);
- };
+ if (!targ.takedamage)
+ return;
- //==============================================================
- // Constructor & Spawn Functions
- //==============================================================
+ // team play damage avoidance
+ // 1998-07-29 Teamplay 1 fix by Maddes start
+ if ((teamplay == 1) && (targ.team > 0) &&
+ (targ.team == attacker.team) && (targ != attacker) &&
+ (attacker.classtype == CT_PLAYER) &&
+ (inflictor.classtype != CT_FUNC_DOOR))
+ {
+ // because squishing a teammate is still possible
+ // 1998-07-29 Teamplay 1 fix by Maddes end
+ return;
+ }
- //--------------------------------------------------------------
- void() base_entity =
- {
- this.classgroup |= CG_ENTITY;
- };
-};
+ // some func_breakables ignore monster damage -- johnfitz
+ // added from Rubicon2 combat.qc -- dumptruck_ds
+ if (targ.classtype == CT_FUNC_BREAKABLE)
+ {
+ if (targ.spawnflags & BREAKABLE_NO_MONSTERS &&
+ attacker.flags & FL_MONSTER)
+ {
+ return;
+ }
+ }
+ // johnfitz
-//------------------------------------------------------------------------------
-// base_tempentity -- QC generated temporary entities
-//------------------------------------------------------------------------------
-class base_tempentity: base_entity
-{
- //--------------------------------------------------------------
- void() base_tempentity =
- {
- this.classgroup |= CG_TEMPENTITY;
+ // used by buttons and triggers to set activator for
+ // target firing
+ damage_attacker = attacker;
+
+ // check for quad damage powerup on the attacker
+ if (attacker.super_damage_finished > time)
+ damage = damage * 4;
+
+ // damage mod for monsters -- dumptruck_ds
+ if (attacker.damage_mod)
+ damage = damage * attacker.damage_mod;
+
+ if (targ.classgroup & CG_ENTITY)
+ ((base_entity)targ).t_damage2_receive (inflictor,
+ attacker, damage);
+ else
+ dprint (sprintf("base_entity::t_damage2: unknown "
+ "entity of type %s\n", targ.classname));
};
-};
-//------------------------------------------------------------------------------
-// temp_delayed_use -- to facilitate delayed SUB_UseTargets
-//------------------------------------------------------------------------------
-class temp_delayed_use: base_tempentity
-{
//--------------------------------------------------------------
- virtual void() delayed_think =
+ nonvirtual void(entity inflictor, entity attacker, float damage)
+ t_damage2_receive =
{
- activator = this.enemy;
- base_mapentity::sub_usetargets ();
- if (this)
- remove (this);
+ local vector dir;
+ local float save;
+ local float take;
+ local float ignore_armor; // johnfitz
+ local string death_type; // johnfitz
+
+ // make sure deathtype doesn't keep stale info after
+ // this function is done -- johnfitz
+ death_type = this.deathtype;
+ this.deathtype = "";
+ // johnfitz
+
+ // don't deplete armor if drowning/burning, or protected by
+ // biosuit/pentagram/godmode (note: in ID1 pentagram/godmode
+ // doesn't actually protect your armor)
+ if (death_type == "burning" || death_type == "drowning" ||
+ this.invincible_finished >= time ||
+ this.flags & FL_GODMODE)
+ {
+ ignore_armor = TRUE;
+ }
+ else
+ {
+ ignore_armor = FALSE;
+ }
+
+ // johnfitz
+ // save damage based on the target's armor level
+ if (ignore_armor)
+ {
+ // johnfitz -- some damage doesn't deplete armor
+ save = 0;
+ }
+ else
+ {
+ save = ceil (this.armortype * damage);
+ if (save >= this.armorvalue)
+ {
+ save = this.armorvalue;
+ // lost all armor
+ this.armortype = 0;
+ this.items = this.items - (this.items &
+ (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3));
+ }
+ }
+
+ this.armorvalue = this.armorvalue - save;
+ take = ceil (damage - save);
+
+ // add to the damage total for clients, which will be sent as a
+ // single message at the end of the frame
+ // FIXME: remove after combining shotgun blasts?
+ if (this.flags & FL_CLIENT)
+ {
+ this.dmg_take = this.dmg_take + take;
+ this.dmg_save = this.dmg_save + save;
+ this.dmg_inflictor = inflictor;
+ }
+
+ // figure momentum add
+ if ((inflictor != world) && (this.movetype == MOVETYPE_WALK))
+ {
+ dir = this.origin -
+ (inflictor.absmin + inflictor.absmax) * 0.5;
+ dir = normalize (dir);
+ this.velocity = this.velocity + dir * damage * 8;
+ }
+
+ // check for godmode, then invincibility
+ // must happen after possibly changing velocity -- CEV
+ if (this.flags & FL_GODMODE)
+ return;
+
+ if (this.invincible_finished >= time)
+ {
+ if (this.invincible_sound < time)
+ {
+ sound (this, CHAN_ITEM, "items/protect3.wav",
+ 1, ATTN_NORM);
+ this.invincible_sound = time + 2;
+ }
+ return;
+ }
+
+ // do the damage
+ this.health = this.health - take;
+
+ // fire pain_target if appropriate
+ if ((this.flags & FL_MONSTER) && this.pain_target != "" &&
+ this.health <= this.pain_threshold)
+ {
+ if (this.classgroup & CG_MONSTER)
+ {
+ ((base_monster)this).sub_pain_use ();
+ }
+ else
+ {
+ dprint (sprintf("base_entity::t_damage2_receive:"
+ " unknown target type %s!\n",
+ this.classname));
+ }
+ }
+
+ if (this.health <= 0)
+ {
+ this.killed (inflictor, attacker);
+ return;
+ }
+
+ // react to the damage
+ if ((this.flags & FL_MONSTER) && attacker != world)
+ {
+ // get mad unless of the same class (except for soldiers)
+ if (this != attacker && attacker != this.enemy)
+ {
+ local float mode;
+ mode = 0;
+
+ // take highest mode so infighting happens
+ // consistently
+ if (this.infight_mode == -1 ||
+ this.infight_mode > mode)
+ {
+ mode = this.infight_mode;
+ }
+
+ if (mode != -1 && attacker.infight_mode > mode)
+ {
+ mode = attacker.infight_mode;
+ }
+
+ // soldiers of the same style will infight
+ // -- dumptruck_ds
+ // thanks for c0burn and Shamblernaut forx
+ // your help!
+ if (mode == -1)
+ {
+ if (attacker.classtype == CT_PLAYER)
+ {
+ if (enemy.classtype==CT_PLAYER)
+ oldenemy = enemy;
+ enemy = attacker;
+ if (this.classgroup & CG_MONSTER)
+ {
+ local base_monster m;
+ m = (base_monster)this;
+ m.ai_foundtarget ();
+ }
+ else
+ {
+ dprint (sprintf(
+ "T_Damage: "
+ "unknown class "
+ "%s!\n",
+ classname));
+ }
+ }
+ }
+ else if ((this.classname != attacker.classname)
+ || ((this.classname == "monster_army")
+ && (this.style == attacker.style)) ||
+ // infight if different models
+ (mode > 0 && this.mdl_body !=
+ attacker.mdl_body) ||
+ // infight if different skin
+ (mode > 1 && this.skin !=
+ attacker.skin) ||
+ // always infight
+ (mode > 2))
+ {
+ if (this.enemy.classname == "player")
+ this.oldenemy = this.enemy;
+ this.enemy = attacker;
+ if (this.classgroup & CG_MONSTER)
+ {
+ local base_monster m1 =
+ (base_monster)this;
+ m1.ai_foundtarget ();
+ }
+ else
+ {
+ dprint (sprintf("T_Damage: "
+ "infight check unk"
+ "nown classname %s\n",
+ this.classname));
+ }
+ }
+ }
+ }
+
+ // TODO CEV
+ this.do_damage (attacker, take);
+ if (skill == 3)
+ this.pain_finished = time + 5;
};
//--------------------------------------------------------------
- void() temp_delayed_use =
+ // Killed
+ //--------------------------------------------------------------
+ nonvirtual void(entity inflictor, entity attacker) killed =
{
- this.classname = "DelayedUse";
- this.classtype = CT_TEMP_DELAYEDUSE;
- this.classgroup = CG_TEMPENTITY;
- this.think = this.delayed_think;
- };
-};
+ if (this.health < -99)
+ // don't let sbar look bad if a player
+ this.health = -99;
+
+ if (movetype == MOVETYPE_NONE ||
+ movetype == MOVETYPE_PUSH ||
+ movetype == MOVETYPE_FLYMISSILE ||
+ movetype == MOVETYPE_BOUNCE)
+ {
+ // doors, triggers, missiles, etc
+ this.do_destroy ();
+ // this.th_die ();
+ return;
+ }
-//------------------------------------------------------------------------------
-// base_mapentity -- spawnable mapper-placeable entities
-//------------------------------------------------------------------------------
-class base_mapentity: base_entity
-{
- //--------------------------------------------------------------
- virtual void(entity attacker, float damage) do_damage = { };
+ this.enemy = attacker;
+
+ // bump the monster counter
+ if (this.flags & FL_MONSTER)
+ {
+ killed_monsters = killed_monsters + 1;
+ WriteByte (MSG_ALL, SVC_KILLEDMONSTER);
+ }
+
+ ClientObituary (this, inflictor, attacker);
+
+ this.takedamage = DAMAGE_NO;
+ this.touch = sub_null;
+
+ // TODO CEV
+ if (this.classgroup & CG_MONSTER)
+ ((base_monster)this).sub_death_use ();
+
+ this.do_destroy ();
+ // this.th_die ();
+ };
//==============================================================
// Subs
//==============================================================
//--------------------------------------------------------------
+ // was CheckValidTouch(); needed for both spawnable map entities
+ // and temporary entities -- CEV
+ //--------------------------------------------------------------
+ nonvirtual float(entity toucher) sub_checkvalidtouch =
+ {
+ if (toucher.classtype != CT_PLAYER)
+ return FALSE;
+ if (toucher.health <= 0)
+ return FALSE;
+ if (toucher.movetype == MOVETYPE_NOCLIP)
+ return FALSE;
+ if (this.estate != STATE_ACTIVE)
+ return FALSE;
+ return TRUE;
+ };
+
+ //--------------------------------------------------------------
nonvirtual void() sub_usetargets =
{
if (this.estate != STATE_ACTIVE)
return;
- local entity otemp = other;
- local entity t;
- local string match = "";
-
if (this.delay)
{
// create a temp object to fire at a later time
- t = spawn (temp_delayed_use,
+ spawn (temp_delayed_use,
enemy: activator,
nextthink: time + this.delay,
message: this.message,
@@ -185,6 +514,10 @@ class base_mapentity: base_entity
return;
}
+ local entity original_other = other;
+ local entity t;
+ local string match = "";
+
// print the message
if (this.message != "" && !(flags & FL_NOCENTERPRINT))
{
@@ -294,8 +627,8 @@ class base_mapentity: base_entity
while (t != world)
{
// TODO CEV
- if (t.classgroup & CG_MAPENTITY)
- ((base_mapentity)t).use ();
+ if (t.classgroup & CG_ENTITY)
+ ((base_entity)t).use ();
else
SUB_UseAsSelf (t, match);
t = find (t, ::targetname, match);
@@ -305,8 +638,8 @@ class base_mapentity: base_entity
while (t != world)
{
// TODO CEV
- if (t.classgroup & CG_MAPENTITY)
- ((base_mapentity)t).use ();
+ if (t.classgroup & CG_ENTITY)
+ ((base_entity)t).use ();
else
SUB_UseAsSelf (t, match);
t = find (t, ::targetname2, match);
@@ -316,8 +649,8 @@ class base_mapentity: base_entity
while (t != world)
{
// TODO CEV
- if (t.classgroup & CG_MAPENTITY)
- ((base_mapentity)t).use ();
+ if (t.classgroup & CG_ENTITY)
+ ((base_entity)t).use ();
else
SUB_UseAsSelf (t, match);
t = find (t, ::targetname3, match);
@@ -327,8 +660,8 @@ class base_mapentity: base_entity
while (t != world)
{
// TODO CEV
- if (t.classgroup & CG_MAPENTITY)
- ((base_mapentity)t).use ();
+ if (t.classgroup & CG_ENTITY)
+ ((base_entity)t).use ();
else
SUB_UseAsSelf (t, match);
t = find (t, ::targetname4, match);
@@ -336,7 +669,7 @@ class base_mapentity: base_entity
}
// reverse the 'other' global before finishing
- other = otemp;
+ other = original_other;
};
//--------------------------------------------------------------
@@ -353,8 +686,8 @@ class base_mapentity: base_entity
while (t != world)
{
// TODO CEV
- if (t.classgroup & CG_MAPENTITY)
- ((base_mapentity)t).use ();
+ if (t.classgroup & CG_ENTITY)
+ ((base_entity)t).use ();
else
SUB_UseAsSelf (t, matchstring);
t = find (t, ::matchfield, matchstring);
@@ -363,6 +696,120 @@ class base_mapentity: base_entity
other = otemp;
};
+ //==============================================================
+ // Interfacing
+ //==============================================================
+
+ // blocked() seems to only be used by func_ entities so it's
+ // undefined here & defined later in the base_func class -- CEV
+
+ //--------------------------------------------------------------
+ virtual void(entity attacker, float damage) do_damage = { };
+
+ //--------------------------------------------------------------
+ virtual void() do_destroy = { };
+
+ //--------------------------------------------------------------
+ virtual void() do_think = { };
+
+ //--------------------------------------------------------------
+ virtual void() think =
+ {
+ // has think been disabled? -- CEV
+ if (this.interaction_flags & DISABLE_THINK)
+ return;
+
+ do_think ();
+ };
+
+ //--------------------------------------------------------------
+ virtual void(entity toucher) do_touch = { };
+
+ //--------------------------------------------------------------
+ virtual void() touch =
+ {
+ // has touch been disabled? -- CEV
+ if (this.interaction_flags & DISABLE_TOUCH)
+ return;
+
+ do_touch (other);
+ };
+
+ //--------------------------------------------------------------
+ virtual void(entity caller) do_use = { };
+
+ //--------------------------------------------------------------
+ virtual void() use =
+ {
+ // has use been disabled? -- CEV
+ if (this.interaction_flags & DISABLE_USE)
+ return;
+
+ do_use (other);
+ };
+
+ //==============================================================
+ // Constructor & Spawn Functions
+ //==============================================================
+
+ //--------------------------------------------------------------
+ void() base_entity =
+ {
+ this.classgroup |= CG_ENTITY;
+ };
+};
+
+//------------------------------------------------------------------------------
+// base_tempentity -- QC generated temporary entities
+//------------------------------------------------------------------------------
+class base_tempentity: base_entity
+{
+ //==============================================================
+ // Interfacing
+ //==============================================================
+
+ //==============================================================
+ // Initialization
+ //==============================================================
+
+ //--------------------------------------------------------------
+ void() base_tempentity =
+ {
+ this.classgroup |= CG_TEMPENTITY;
+ };
+};
+
+//------------------------------------------------------------------------------
+// temp_delayed_use -- to facilitate delayed SUB_UseTargets
+//------------------------------------------------------------------------------
+class temp_delayed_use: base_tempentity
+{
+ //--------------------------------------------------------------
+ virtual void() think =
+ {
+ activator = this.enemy;
+ this.sub_usetargets ();
+ remove (this);
+ };
+
+ //--------------------------------------------------------------
+ void() temp_delayed_use =
+ {
+ this.classname = "DelayedUse";
+ this.classtype = CT_TEMP_DELAYEDUSE;
+ this.classgroup = CG_TEMPENTITY;
+ };
+};
+
+//------------------------------------------------------------------------------
+// base_mapentity -- spawnable mapper-placeable entities
+//------------------------------------------------------------------------------
+class base_mapentity: base_entity
+{
+ //==============================================================
+ // Subs
+ //==============================================================
+
//--------------------------------------------------------------
nonvirtual void() sub_setmovedir =
{
@@ -401,7 +848,7 @@ class base_mapentity: base_entity
};
//==============================================================
- // Constructor & Spawn Functions
+ // Initialization
//==============================================================
//--------------------------------------------------------------
@@ -411,17 +858,16 @@ class base_mapentity: base_entity
// The SPAWNFLAG constants & setup functions are defined elsewhere;
// see newflags.qc for documentation.
//--------------------------------------------------------------
- virtual float() inhibit =
+ virtual float() sub_inhibit =
{
- if (coop && (this.spawnflags & SPAWNFLAG_NOT_IN_COOP))
+ if (coop && (spawnflags & SPAWNFLAG_NOT_IN_COOP))
{
total_not_in_coop = total_not_in_coop + 1;
remove (this);
return TRUE;
}
- if (!coop && !deathmatch &&
- (this.spawnflags & SPAWNFLAG_NOT_IN_SP))
+ if (!coop && !deathmatch && (spawnflags & SPAWNFLAG_NOT_IN_SP))
{
total_not_in_sp = total_not_in_sp + 1;
remove (this);
@@ -434,7 +880,7 @@ class base_mapentity: base_entity
if (!deathmatch)
{
if (skill == 2 &&
- (this.spawnflags & SPAWNFLAG_NOT_ON_SKILL2))
+ (spawnflags & SPAWNFLAG_NOT_ON_SKILL2))
{
total_not_on_skill2 = total_not_on_skill2 + 1;
remove (this);
@@ -442,7 +888,7 @@ class base_mapentity: base_entity
}
if (skill == 3 &&
- (this.spawnflags & SPAWNFLAG_NOT_ON_SKILL3))
+ (spawnflags & SPAWNFLAG_NOT_ON_SKILL3))
{
total_not_on_skill3 = total_not_on_skill3 + 1;
remove (this);
@@ -470,7 +916,7 @@ class base_mapentity: base_entity
{
// new spawnflags for all entities -- iw
// "all entities", well, all base_mapentities anyway -- CEV
- if (inhibit())
+ if (sub_inhibit())
return;
// this is from Nuclide -- CEV
Return to the top of this page or return to the overview of this repo.
Diff qc/base_func.qc
diff --git a/qc/base_func.qc b/qc/base_func.qc
index c1c64f0..858a045 100644
--- a/qc/base_func.qc
+++ b/qc/base_func.qc
@@ -35,6 +35,10 @@ class base_func: base_mapentity
if (this.interaction_flags & DISABLE_BLOCKED)
return;
+ // don't call blocked when stopped by a projectile -- CEV
+ if (other.classgroup & CG_PROJECTILE)
+ return;
+
do_blocked (other);
};
@@ -124,6 +128,9 @@ class base_func: base_mapentity
}
};
+ //--------------------------------------------------------------
+ virtual void() think1 = { };
+
//==============================================================
// Constructor & Spawn Functions
//==============================================================
Return to the top of this page or return to the overview of this repo.
Diff qc/base_monster.qc
diff --git a/qc/base_monster.qc b/qc/base_monster.qc
index 3e8f2fa..18052e5 100644
--- a/qc/base_monster.qc
+++ b/qc/base_monster.qc
@@ -2,19 +2,32 @@
// base_monster.qc -- base monster class, monster logic
//==============================================================================
-// constants -- any states should start at -1 and decrement because
+//======================================================================
+// constants
+//======================================================================
+
+// think and use states should start at -1 and decrement because
// subclasses will start at 0 and work up -- CEV
const float MONSTER_THINK_START = -1;
const float MONSTER_THINK_FOUNDTARGET = -2;
-
const float MONSTER_USE_MAKEANGRY = -1;
const float MONSTER_USE_TELEDELAY = -2;
+// spawnflags
const float NO_SIGHT_SOUND = 32;
const float PASSIVE_UNTIL_ATTACKED = 64;
const float PASSIVE_ALWAYS = 128;
+// values for attack_state field (defined in base_monster below)
+const float AS_STRAIGHT = 1;
+const float AS_SLIDING = 2;
+const float AS_MELEE = 3;
+const float AS_MISSILE = 4;
+const float AS_TURRET = 5;
+
+//======================================================================
// globals
+//======================================================================
entity sight_entity; // was in ai.qc
float sight_entity_time; // was in ai.qc
float enemy_vis; // was in fight.qc
@@ -22,13 +35,6 @@ float enemy_infront; // was in fight.qc
float enemy_range; // was in fight.qc
float enemy_yaw; // was in fight.qc
-// fields -- define Preach's new fields dumptruck_ds
-.string tele_model;
-.vector tele_mins;
-.vector tele_maxs;
-.float tele_solid;
-.float tele_movetype;
-
//======================================================================
// .enemy
// Will be world if not currently angry at anyone.
@@ -59,7 +65,7 @@ float enemy_yaw; // was in fight.qc
// monster_update_total
//
// Call this function to safely update total_monsters when the game is
-// in progress. It adds "n" to total_monsters, then notifies all clients
+// in progress. It adds "n" to total_monsters, then notifies all clients
// of the change. -- iw
//----------------------------------------------------------------------
void(float n) monster_update_total =
@@ -74,8 +80,16 @@ void(float n) monster_update_total =
//------------------------------------------------------------------------------
class base_monster: base_mapentity
{
+ float attack_state;
+ float touch_time;
float use_flag;
+ string tele_model; // Preach's new fields -- dumptruck_ds
+ vector tele_mins;
+ vector tele_maxs;
+ float tele_solid;
+ float tele_movetype;
+
// the typical th_ monster think functions -- CEV
virtual void() think_stand = {};
virtual void() think_walk = {};
@@ -85,6 +99,377 @@ class base_monster: base_mapentity
virtual void() think_turret = {};
//==============================================================
+ // Generic Monster Weapon Firing
+ //==============================================================
+
+ //--------------------------------------------------------------
+ // BDW_OgreFireFlak
+ //--------------------------------------------------------------
+ nonvirtual void(vector org, float projspeed) fire_flak =
+ {
+ local float flakcount = 8;
+ local vector dir, ang;
+
+ this.effects = this.effects | EF_MUZZLEFLASH;
+ sound (this, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
+
+ // make angles out of the current displacement vector...
+ ang = vectoangles (this.enemy.origin - this.origin);
+ // then get the required components...
+ makevectors (ang);
+
+ while (flakcount > 0)
+ {
+ // tighter spread...
+ dir = v_forward * 10 +
+ crandom() * v_right +
+ crandom() * v_up;
+ dir = normalize (dir);
+ // f*cking hack...is this a v_forward problem?
+ dir_z *= -1;
+ // SetSpeed -- CEV
+ dir *= min (projspeed * (this.proj_speed_mod ?
+ this.proj_speed_mod : 1), frame_maxvelocity);
+
+ spawn (projectile_flak,
+ // this is a hack to tell FlakTouch that
+ // it came from an ogre
+ spawnflags: MONSTER_FLAK_OGRE,
+ owner: this,
+ // origin offset suitable for an ogre -- CEV
+ origin: org,
+ velocity: dir,
+ // parameters for homing
+ homing: this.homing,
+ enemy: this.enemy,
+ proj_speed_mod: this.proj_speed_mod,
+ waitmin: this.waitmin,
+ // model & skin
+ mdl_proj: this.mdl_proj,
+ skin_proj: this.skin_proj,
+ // sound
+ snd_hit: this.snd_hit);
+
+ flakcount -= 1;
+ }
+ };
+
+ //--------------------------------------------------------------
+ // Monster grenade function, incorporates PreachFireGrenade -- CEV
+ //--------------------------------------------------------------
+ nonvirtual void(vector org, float direct, float splash,
+ float elevation) fire_grenade =
+ {
+ local vector missile_velocity = '0 0 0';
+
+ this.effects = this.effects | EF_MUZZLEFLASH;
+ sound (this, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
+
+ // set missile speed
+ if (elevation)
+ {
+ local vector ang = this.angles;
+ ang_x = -elevation;
+ makevectors (ang);
+ missile_velocity = v_forward * GRENADE_SPEED;
+ }
+ else
+ {
+ missile_velocity =
+ normalize (this.enemy.origin - this.origin);
+ missile_velocity *= 600;
+ missile_velocity_z = 200;
+ }
+
+ spawn (projectile_grenade,
+ owner: this,
+ origin: org,
+ velocity: missile_velocity,
+ direct_damage: direct,
+ splash_damage: splash,
+ mdl_proj: this.mdl_proj,
+ skin_proj: this.skin_proj,
+ // sound
+ snd_hit: this.snd_hit);
+ };
+
+ //--------------------------------------------------------------
+ // hknight_shot
+ //--------------------------------------------------------------
+ nonvirtual void(vector org, vector dir, float off) fire_hknightspell =
+ {
+ // set missile speed
+ dir = normalize (v_forward);
+ dir_z = 0 - dir_z + (random() - 0.5) * 0.1;
+ dir *= min (HKNSPELL_SPEED * (this.proj_speed_mod ?
+ this.proj_speed_mod : 1), frame_maxvelocity);
+
+ spawn (projectile_hknightspell,
+ owner: this,
+ origin: org,
+ velocity: dir,
+ projexpl: this.projexpl,
+ // parameters for homing
+ homing: this.homing,
+ enemy: this.enemy,
+ proj_speed_mod: this.proj_speed_mod,
+ waitmin: this.waitmin,
+ // model & skin
+ mdl_proj: this.mdl_proj,
+ skin_proj: this.skin_proj,
+ snd_hit: this.snd_hit,
+ // unique to this magic missile
+ spell_offset: off);
+
+ sound_attack (this, CHAN_WEAPON, "hknight/attack1.wav",
+ 1, ATTN_NORM);
+ };
+
+ //--------------------------------------------------------------
+ // Enforcer lasers, was LaunchLaser
+ //--------------------------------------------------------------
+ nonvirtual void(vector org, vector dir) fire_laser =
+ {
+ this.effects = this.effects | EF_MUZZLEFLASH;
+ sound_attack (this, CHAN_WEAPON, "enforcer/enfire.wav",
+ 1, ATTN_NORM);
+
+ dir = normalize (dir);
+ // SetSpeed (newmis, vec, projspeed);
+ dir *= min (LASER_SPEED * (this.proj_speed_mod ?
+ this.proj_speed_mod : 1), frame_maxvelocity);
+
+ spawn (projectile_laser,
+ owner: this,
+ origin: org,
+ velocity: dir,
+ homing: this.homing,
+ enemy: this.enemy,
+ proj_speed_mod: this.proj_speed_mod,
+ snd_hit: this.snd_hit,
+ mdl_proj: this.mdl_proj,
+ skin_proj: this.skin_proj);
+ };
+
+ //--------------------------------------------------------------
+ nonvirtual void(vector org, vector dir, float projspeed) fire_lavaball =
+ {
+ dir = normalize (dir);
+ // SetSpeed
+ dir *= min (projspeed * (this.proj_speed_mod ?
+ this.proj_speed_mod : 1), frame_maxvelocity);
+
+ spawn (projectile_lavaball,
+ owner: this,
+ origin: org,
+ velocity: dir,
+ // custom spin of projectile - monster_shambler
+ avelocity: this.cust_avelocity,
+ homing: this.homing,
+ enemy: this.enemy,
+ proj_basespeed: projspeed,
+ proj_speed_mod: this.proj_speed_mod,
+ mdl_proj: this.mdl_proj,
+ skin_proj: this.skin_proj,
+ // sound
+ snd_hit: this.snd_hit);
+ };
+
+ //--------------------------------------------------------------
+ // DOE multigrenades
+ //--------------------------------------------------------------
+ nonvirtual void() fire_multigrenade =
+ {
+ local vector missile_velocity;
+
+ sound (this, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
+
+ // this.punchangle_x = -2;
+
+ // set missile speed
+ missile_velocity = normalize (this.enemy.origin - this.origin);
+ missile_velocity *= 600;
+ missile_velocity_z = 200;
+
+ spawn (projectile_multigrenade,
+ owner: this,
+ origin: this.origin + '0 0 16',
+ velocity: missile_velocity,
+ // dumptruck_ds
+ skin: this.skin_proj,
+ snd_hit: this.snd_hit);
+ };
+
+ //--------------------------------------------------------------
+ nonvirtual void(vector org, vector dir, float direct, float splash,
+ float projspeed) fire_rocket =
+ {
+ this.effects = this.effects | EF_MUZZLEFLASH;
+ sound_attack (this, CHAN_WEAPON, "weapons/sgun1.wav",
+ 1, ATTN_NORM);
+
+ dir = normalize (dir);
+ // SetSpeed
+ dir *= min (projspeed * (this.proj_speed_mod ?
+ this.proj_speed_mod : 1), frame_maxvelocity);
+
+ spawn (projectile_rocket,
+ owner: this,
+ origin: org,
+ velocity: dir,
+ direct_damage: direct,
+ splash_damage: splash,
+ homing: this.homing,
+ enemy: this.enemy,
+ proj_basespeed: projspeed,
+ proj_speed_mod: this.proj_speed_mod,
+ mdl_proj: this.mdl_proj,
+ skin_proj: this.skin_proj,
+ // sound
+ snd_hit: this.snd_hit);
+ };
+
+ //--------------------------------------------------------------
+ nonvirtual void(vector org, vector dir, float damage, float projspeed)
+ fire_spike =
+ {
+ dir = normalize (dir);
+ // SetSpeed
+ dir *= min (projspeed * (this.proj_speed_mod ?
+ this.proj_speed_mod : 1), frame_maxvelocity);
+
+ spawn (projectile_spike,
+ owner: this,
+ origin: org,
+ velocity: dir,
+ direct_damage: damage,
+ // homing fields
+ homing: this.homing,
+ enemy: this.enemy,
+ proj_basespeed: projspeed,
+ proj_speed_mod: this.proj_speed_mod,
+ // model fields
+ mdl_proj: this.mdl_proj,
+ skin_proj: this.skin_proj,
+ // sound
+ snd_hit: this.snd_hit);
+ };
+
+ //--------------------------------------------------------------
+ // ShalMissile
+ //--------------------------------------------------------------
+ nonvirtual void(vector org, vector dir) fire_voreball =
+ {
+ local float basespeed;
+
+ this.effects = this.effects | EF_MUZZLEFLASH;
+ sound_misc (this, CHAN_WEAPON, "shalrath/attack2.wav",
+ 1, ATTN_NORM);
+
+ dir = normalize (dir);
+ // SetSpeed
+ dir *= min (VOREBALL_SPEED * proj_speed_mod, frame_maxvelocity);
+
+ if (skill == 3)
+ basespeed = 350 * this.proj_speed_mod;
+ else
+ basespeed = 250 * this.proj_speed_mod;
+
+ spawn (projectile_voreball,
+ owner: this,
+ enemy: this.enemy,
+ origin: org,
+ velocity: dir,
+ avelocity: this.cust_avelocity,
+ homing: this.homing,
+ proj_basespeed: basespeed,
+ proj_speed_mod: this.proj_speed_mod,
+ mdl_proj: this.mdl_proj,
+ skin_proj: this.skin_proj,
+ // sound
+ snd_hit: this.snd_hit);
+ };
+
+ //--------------------------------------------------------------
+ // Wiz_StartFast
+ //--------------------------------------------------------------
+ nonvirtual void() fire_wizardspell =
+ {
+ this.v_angle = this.angles;
+ makevectors (this.angles);
+
+ spawn (projectile_wizardspell,
+ owner: this,
+ enemy: this.enemy,
+ origin: this.origin + '0 0 30' +
+ v_forward * 14 + v_right * 14,
+ movedir: v_right,
+ proj_basespeed: WIZMIS_SPEED,
+ proj_speed_mod: this.proj_speed_mod,
+ projexpl: this.projexpl,
+ // two nextthinks were present in Wiz_StartFast,
+ // I'm leaving the last of them -- CEV
+ // nextthink: time + 0.6,
+ nextthink: time + 0.8);
+
+ spawn (projectile_wizardspell,
+ owner: this,
+ enemy: this.enemy,
+ origin: this.origin + '0 0 30' +
+ v_forward * 14 + v_right * -14,
+ movedir: '0 0 0' - v_right,
+ proj_basespeed: WIZMIS_SPEED,
+ proj_speed_mod: this.proj_speed_mod,
+ projexpl: this.projexpl,
+ // two nextthinks were present in Wiz_StartFast,
+ // I'm leaving the last of them -- CEV
+ // nextthink: time + 1,
+ nextthink: time + 0.3);
+ };
+
+ //--------------------------------------------------------------
+ // Throw a zombie gib; incorporates PreachFireGrenade -- CEV
+ //--------------------------------------------------------------
+ nonvirtual void(vector offset, float elevation) fire_zombiechunk =
+ {
+ local vector missile_velocity = '0 0 0';
+
+ sound_attack (this, CHAN_WEAPON, "zombie/z_shot1.wav",
+ 1, ATTN_NORM);
+
+ // set missile speed
+ if (elevation)
+ {
+ // PreachFireZombie -- for Z-Aware Zombies
+ local vector ang = this.angles;
+ ang_x = -elevation;
+ makevectors (ang);
+ missile_velocity = v_forward * ZCHUNK_SPEED;
+ }
+ else
+ {
+ // calc org
+ offset = offset_x * v_forward +
+ offset_y * v_right + (offset_z - 24) * v_up;
+ local vector org = this.origin + offset;
+
+ makevectors (this.angles);
+ missile_velocity = normalize (this.enemy.origin - org);
+ missile_velocity = missile_velocity * ZCHUNK_SPEED;
+ missile_velocity_z = 200;
+ }
+
+ spawn (projectile_zombiechunk,
+ owner: this,
+ origin: this.origin + offset,
+ velocity: missile_velocity,
+ mdl_proj: this.mdl_proj,
+ skin_proj: this.skin_proj,
+ // sound
+ snd_hit: this.snd_hit);
+ };
+
+ //==============================================================
// Monster AI
//==============================================================
@@ -450,7 +835,7 @@ class base_monster: base_mapentity
nonvirtual void() ai_face =
{
this.ideal_yaw = vectoyaw (this.enemy.origin - this.origin);
- ChangeYaw ();
+ changeyaw ();
};
//--------------------------------------------------------------
@@ -550,7 +935,7 @@ class base_monster: base_mapentity
if (ai_findtarget())
return;
- ChangeYaw ();
+ changeyaw ();
};
//--------------------------------------------------------------
@@ -560,7 +945,7 @@ class base_monster: base_mapentity
nonvirtual void() ai_run_melee =
{
this.ideal_yaw = enemy_yaw;
- ChangeYaw ();
+ changeyaw ();
if (ai_facing_ideal())
{
@@ -577,7 +962,7 @@ class base_monster: base_mapentity
{
this.ideal_yaw = enemy_yaw;
// dprint ("ai_run_missile GO\n");
- ChangeYaw ();
+ changeyaw ();
if (this.ai_facing_ideal())
{
if (this.spawnflags & I_AM_TURRET)
@@ -603,7 +988,7 @@ class base_monster: base_mapentity
local float ofs;
this.ideal_yaw = enemy_yaw;
- ChangeYaw ();
+ changeyaw ();
if (this.lefty)
ofs = 90;
else
@@ -704,29 +1089,29 @@ class base_monster: base_mapentity
if (time < this.t_length)
{
// if orientation is forced
- ChangeYaw ();
+ changeyaw ();
if (walkmove(this.ideal_yaw, dist))
return;
// dodge left
this.ideal_yaw += 30;
- ChangeYaw ();
+ changeyaw ();
if (walkmove(this.ideal_yaw, dist))
return;
// dodge right
this.ideal_yaw -= 60;
- ChangeYaw ();
- ChangeYaw ();
+ changeyaw ();
+ changeyaw ();
if (walkmove(this.ideal_yaw, dist))
return;
// give up
this.ideal_yaw += 30;
- ChangeYaw();
+ changeyaw();
// lose patience
this.touch_time = this.touch_time - 0.1;
@@ -758,7 +1143,7 @@ class base_monster: base_mapentity
// aim to the left of the enemy for a flyby
this.ideal_yaw = vectoyaw (this.enemy.origin - this.origin);
- ChangeYaw ();
+ changeyaw ();
makevectors (this.angles);
dtemp = this.enemy.origin - 30 * v_right;
@@ -785,7 +1170,7 @@ class base_monster: base_mapentity
return;
ldmg = (random() + random() + random()) * 3;
- T_Damage (this.enemy, this, this, ldmg);
+ this.t_damage2 (this.enemy, this, this, ldmg);
};
//--------------------------------------------------------------
@@ -805,11 +1190,11 @@ class base_monster: base_mapentity
if (vlen(delta) > 60)
return;
- if (!CanDamage(this.enemy, this))
+ if (!this.can_damage(this, this.enemy))
return;
ldmg = (random() + random() + random()) * 3;
- T_Damage (this.enemy, this, this, ldmg);
+ this.t_damage2 (this.enemy, this, this, ldmg);
};
//==============================================================
@@ -963,7 +1348,7 @@ class base_monster: base_mapentity
//==============================================================
//--------------------------------------------------------------
- // think is reassigned in subclasses & so isn't defined here
+ // think is reassigned in subclasses so isn't defined here -- CEV
//--------------------------------------------------------------
/*
virtual void() think = { };
@@ -1406,8 +1791,7 @@ class base_walkmonster: base_monster
{
dprint (sprintf("\n\n%s "
"in wall at: %v\n\n",
- this.classname,
- this.origin));
+ this.classname, this.origin));
}
}
}
Return to the top of this page or return to the overview of this repo.
Diff qc/base_projectile.qc
diff --git a/qc/base_projectile.qc b/qc/base_projectile.qc
index 9553708..0a386a5 100644
--- a/qc/base_projectile.qc
+++ b/qc/base_projectile.qc
@@ -2,6 +2,29 @@
// base_projectile.qc -- generated projectile entities
//==============================================================================
+/*
+Projectile init checklist, required & optional settings, in suggested
+order, for reference when writing a projectile constructor function
+
+1. classtype & classname (required)
+2. movetype & solid (required)
+3. set explosive if necessary (parse_projexpl)
+4. set health and takedamage if desired (for explosives)
+5. angles (required) & avelocity
+6. check (and set if necessary) proj_basespeed
+7. check (and set if necessary) direct_damage and splash_damage
+8. setmodel and skin (required)
+9. setup_homing
+10. setsize, setorigin (required)
+11. think & nextthink (if not capable of homing)
+
+see the files in projectiles/ for examples -- CEV
+*/
+
+//======================================================================
+// Constants
+//======================================================================
+
enum
{
EXPLOSION_THINK_1, // explosion frame/think tracking
@@ -13,19 +36,39 @@ enum
EXPLOSION_THINK_REMOVE
};
+const float BOUNCE_BACKOFF = 1.5; // MOVETYPE_BOUNCE clipvel mult; id1 1.5
+const float BOUNCE_MIN_ZVEL = 60; // MOVETYPE_BOUNCE stop if _z less than
+
//------------------------------------------------------------------------------
-class base_projectile: base_tempentity
+// standard id1 explosion sprite + a few helper functions -- CEV
+//------------------------------------------------------------------------------
+class base_explosion: base_tempentity
{
+ float explosion_think_state;
+
//--------------------------------------------------------------
- void() base_projectile =
+ static void(vector org) write_explosion =
{
- this.classgroup |= CG_PROJECTILE;
+ 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);
};
-};
-class base_explosion: base_tempentity
-{
- float explosion_think_state;
+ //--------------------------------------------------------------
+ static void(vector org) write_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);
+ };
+
+ //==============================================================
+ // Interaction
+ //==============================================================
//--------------------------------------------------------------
virtual void() think =
@@ -51,6 +94,10 @@ class base_explosion: base_tempentity
// sub_null - no-op
};
+ //==============================================================
+ // Initialization
+ //==============================================================
+
//--------------------------------------------------------------
void() base_explosion =
{
@@ -66,3 +113,369 @@ class base_explosion: base_tempentity
this.think ();
};
};
+
+//------------------------------------------------------------------------------
+class base_projectile: base_tempentity
+{
+ float explosive; // set TRUE if explosive projectile
+ float direct_damage; // for t_damage
+ float splash_damage; // for t_radiusdamage
+
+ //--------------------------------------------------------------
+ static float(float testexpl, float offset) parse_projexpl =
+ {
+ return testexpl == 1 ||
+ (testexpl == 2 && offset % 2 == 0) ||
+ (testexpl == 3 && random() * 2 < 1);
+ };
+
+ //--------------------------------------------------------------
+ // I'm sure there's a better way to do this -- CEV
+ //--------------------------------------------------------------
+ static void(base_projectile p) write_projectile_impact =
+ {
+ WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
+ if (p.snd_hit != __NULL__ && p.snd_hit != "")
+ {
+ // dumptruck_ds
+ sound (p, CHAN_WEAPON, p.snd_hit, 1, ATTN_STATIC);
+ WriteByte (MSG_BROADCAST, TE_GUNSHOT);
+ }
+ else if (p.classtype == CT_PROJECTILE_WIZARDMISSILE)
+ {
+ WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
+ }
+ else if (p.classtype == CT_PROJECTILE_HKNIGHT)
+ {
+ WriteByte (MSG_BROADCAST, TE_KNIGHTSPIKE);
+ }
+ else
+ {
+ WriteByte (MSG_BROADCAST, TE_SPIKE);
+ }
+ WriteCoord (MSG_BROADCAST, p.origin_x);
+ WriteCoord (MSG_BROADCAST, p.origin_y);
+ WriteCoord (MSG_BROADCAST, p.origin_z);
+ };
+
+ //--------------------------------------------------------------
+ nonvirtual void() think_homing =
+ {
+ local vector dir, vtemp;
+ vtemp = this.enemy.origin + '0 0 10';
+
+ if (this.enemy.health < 1)
+ {
+ remove (this);
+ return;
+ }
+
+ dir = normalize (vtemp - this.origin);
+ // can't do better than 100% homing
+ if (this.homing < 1 && this.homing > 0)
+ {
+ // This finds a vector somewhere between the vector
+ // the projectile is currently travelling on and
+ // the vector that it would normally snap to for
+ // homing
+ //
+ // homing = .25 means it will go 25% to the new
+ // direction, but keep 75% of the original vector,
+ // resulting in a wider turning range.
+ dir = normalize((dir * this.homing) +
+ normalize(this.velocity * (1 - this.homing)));
+ }
+
+ if (!this.avelocity)
+ this.angles = vectoangles (dir);
+
+ // SetSpeed
+ this.velocity = dir * min (proj_basespeed, frame_maxvelocity);
+
+ if (this.homing > 0)
+ {
+ if (this.homing < 1 && this.attack_finished &&
+ this.attack_finished < time)
+ {
+ // dprint("incrementing homing | ");
+ // dprint("old: ");
+ // dprint(ftos(this.homing));
+ // dprint(" | new: ");
+ this.homing = this.homing + 0.005;
+ // dprint(ftos(this.homing));
+ // dprint("\n");
+ }
+
+ this.nextthink = time + 0.2;
+ this.think = think_homing;
+ }
+ };
+
+ //--------------------------------------------------------------
+ nonvirtual void(float speed) setup_homing =
+ {
+ local vector dir;
+ local float dist, flytime, speedmod;
+
+ if (this.proj_speed_mod > 1)
+ speedmod = 1 / this.proj_speed_mod;
+ else if (speed > 250)
+ speedmod = 1 / (speed / 250);
+ else
+ speedmod = 1;
+
+ dir = normalize ((this.enemy.origin + '0 0 10') - this.origin);
+ dist = vlen (this.enemy.origin - this.origin);
+ flytime = dist * 0.002 * speedmod;
+ if (flytime < 0.1)
+ flytime = 0.1;
+
+ this.proj_basespeed = speed;
+ this.think = think_homing;
+ this.nextthink = flytime + time;
+ if (this.waitmin > 0)
+ // store time to start increasing
+ this.attack_finished = time + this.waitmin;
+ };
+
+ //==============================================================
+ // Interaction
+ //==============================================================
+
+ //--------------------------------------------------------------
+ // was T_MissileTouch -- CEV
+ //--------------------------------------------------------------
+ virtual void(entity toucher) do_touch_explosive =
+ {
+ // standard id1 behavior is to add 1-20 on a direct hit.
+ // I've removed that here. -- CEV
+ // damg = direct_damage + random() * 20;
+
+ if (toucher.health)
+ {
+ // TODO CEV
+ if (toucher.classname == "monster_shambler")
+ // mostly immune
+ t_damage2 (toucher, this, this.owner,
+ direct_damage * 0.5);
+ else
+ t_damage2 (toucher, this, this.owner,
+ direct_damage);
+ }
+
+ // do before radius damage -- CEV
+ if (this.takedamage)
+ this.takedamage = DAMAGE_NO;
+
+ // don't do radius damage to the other, because all the damage
+ // was done in the impact
+ t_radiusdamage2 (this, this.owner, splash_damage, toucher);
+
+ // sound (this, CHAN_WEAPON, "weapons/r_exp3.wav",
+ // 1, ATTN_NORM);
+ this.origin = this.origin - 8 * normalize (this.velocity);
+
+ // BecomeExplosion
+ base_explosion::write_explosion (this.origin);
+ spawn (base_explosion, origin: this.origin);
+ remove (this);
+ };
+
+ //--------------------------------------------------------------
+ // was spike_touch; override if you need to implement special
+ // projectile damage logic -- CEV
+ //--------------------------------------------------------------
+ virtual void(entity toucher) do_touch =
+ {
+ // hit something that bleeds
+ if (other.takedamage)
+ {
+ spawn_touchblood (direct_damage);
+ t_damage2 (toucher, this, this.owner, direct_damage);
+ }
+ else
+ {
+ base_projectile::write_projectile_impact (this);
+ }
+
+ remove (this);
+ };
+
+ //--------------------------------------------------------------
+ virtual void() touch =
+ {
+ // duplicated functionality from base_entity -- CEV
+ if (this.interaction_flags & DISABLE_TOUCH)
+ return;
+
+ // don't damage or touch owner -- CEV
+ if (other == this.owner)
+ return;
+
+ // remove any projectile that hits the sky -- CEV
+ if (pointcontents(this.origin) == CONTENT_SKY)
+ {
+ remove (this);
+ return;
+ }
+
+ if (other.solid == SOLID_TRIGGER)
+ // trigger field, do nothing
+ return;
+
+ if (this.explosive)
+ do_touch_explosive (other);
+ else
+ do_touch (other);
+ };
+
+ //==============================================================
+ // Initialization
+ //==============================================================
+
+ //--------------------------------------------------------------
+ void() base_projectile =
+ {
+ this.classgroup |= CG_PROJECTILE;
+
+ // default value for proj_speed_mod is 1 -- CEV
+ if (!this.proj_speed_mod)
+ this.proj_speed_mod = 1;
+ };
+};
+
+//------------------------------------------------------------------------------
+// Custom Physics for projectiles. Subclass this if you want a projectile
+// to have a fixed size for other objects to collide with but zero size
+// when moving through the world. Useful for creating shootable grenades
+// and missiles. This is slower than engine physics so use sparingly. -- CEV
+//------------------------------------------------------------------------------
+class base_projectile_qcphys: base_projectile
+{
+ //--------------------------------------------------------------
+ // This is a vague imitation of SV_Physics_Toss as found in
+ // Ironwail but with a fixed mins and maxs of '0 0 0' when
+ // testing movement. -- CEV
+ //--------------------------------------------------------------
+ virtual void() customphysics =
+ {
+ if (this.think && this.nextthink > 0.0f)
+ {
+ if (this.nextthink < time)
+ {
+ this.nextthink = 0.0f;
+ this.think ();
+ }
+ }
+
+ // were we removed by think?
+ if (!this)
+ return;
+
+ // are we onground?
+ if (this.flags & FL_ONGROUND)
+ return;
+
+ // move angles
+ if (this.avelocity)
+ this.angles += this.avelocity * frametime;
+
+ // apply gravity if desired
+ if (this.movetype == MOVETYPE_BOUNCE)
+ {
+ local float grav = this.gravity ? this.gravity : 1.0;
+ this.velocity_z -= grav * frame_gravity * frametime;
+ }
+
+ // test the move with a fixed mins and maxs of '0 0 0' and
+ // suitable flags for FLYMISSILE if set -- CEV
+ tracebox (this.origin, '0 0 0', '0 0 0',
+ this.origin + (this.velocity * frametime),
+ movetype == MOVETYPE_FLYMISSILE ? MOVE_MISSILE : FALSE,
+ this.owner);
+
+ if (trace_allsolid || trace_startsolid)
+ {
+ dprint (sprintf("base_projectile_qcphys::custom"
+ "physics: in a solid at %v\n", trace_endpos));
+
+ if (this.movetype == MOVETYPE_BOUNCE)
+ {
+ // TODO CEV figure out what to do here
+ return;
+ }
+ else
+ {
+ // in the world, so just explode
+ local entity oldother2 = other;
+ other = world;
+ this.touch ();
+ other = oldother2;
+ return;
+ }
+ }
+
+ // clear to accept the move
+ setorigin (this, trace_endpos);
+
+ if (trace_fraction >= 1.0f)
+ // didn't hit anything
+ return;
+
+ // immediate clipvelocity for MOVETYPE_BOUNCE -- CEV
+ if (this.movetype == MOVETYPE_BOUNCE)
+ {
+ this.velocity -= trace_plane_normal *
+ ((this.velocity * trace_plane_normal) *
+ BOUNCE_BACKOFF);
+
+ // set ONGROUND while we're at it -- CEV
+ if (trace_plane_normal_z > 0.7)
+ {
+ if (this.velocity_z < BOUNCE_MIN_ZVEL)
+ {
+ this.flags |= FL_ONGROUND;
+ this.groundentity = trace_ent;
+ this.groundnormal = trace_plane_normal;
+ this.velocity = '0 0 0';
+ this.avelocity = '0 0 0';
+ }
+ }
+ }
+
+ // SV_Impact lookalike -- CEV
+ local entity oldother = other;
+ if (trace_ent)
+ {
+ // we can make some assumptions and skip a few
+ // checks here -- CEV
+ if (trace_ent)
+ other = trace_ent;
+ else
+ other = world;
+ this.touch ();
+
+ // check trace_ent again just in case the call
+ // to touch above somehow removed it -- CEV
+ if (trace_ent && trace_ent.touch &&
+ trace_ent.solid != SOLID_NOT)
+ {
+ if (this)
+ other = this;
+ else
+ other = world;
+
+ // check classgroup before cast -- CEV
+ if (trace_ent.classgroup & CG_ENTITY)
+ ((base_entity)trace_ent).touch ();
+ }
+ }
+ else if (trace_fraction < 1.0f)
+ {
+ // for the bounce sound
+ other = world;
+ this.touch ();
+ }
+ other = oldother;
+ };
+};
Return to the top of this page or return to the overview of this repo.
Diff qc/client/connect.qc
diff --git a/qc/client/connect.qc b/qc/client/connect.qc
deleted file mode 100644
index 6b2fe77..0000000
--- a/qc/client/connect.qc
+++ /dev/null
@@ -1,37 +0,0 @@
-//==============================================================================
-// client/connect.qc
-//==============================================================================
-
-//----------------------------------------------------------------------
-// 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;
-
- // let everyone else know
- bprint (self.netname);
- bprint (" left the game with ");
- bprint (ftos(self.frags));
- bprint (" frags\n");
- sound (self, CHAN_BODY, "player/tornoff2.wav", 1, ATTN_NONE);
- set_suicide_frame ();
-};
Return to the top of this page or return to the overview of this repo.
Diff qc/client/impulse.qc
diff --git a/qc/client/impulse.qc b/qc/client/impulse.qc
deleted file mode 100644
index e7a9b6d..0000000
--- a/qc/client/impulse.qc
+++ /dev/null
@@ -1,316 +0,0 @@
-//==============================================================================
-// client/impulse.qc -- impulse commands
-//==============================================================================
-
-//----------------------------------------------------------------------
-// CheatCommand
-//----------------------------------------------------------------------
-void() CheatCommand =
-{
- // 1998-07-29 Cheats coop fix by Maddes start
- // if (deathmatch || coop)
- if (deathmatch)
- // 1998-07-29 Cheats coop fix by Maddes end
- return;
-
- self.ammo_cells = 200;
- self.ammo_nails = 200;
- self.ammo_rockets = 100;
- self.ammo_shells = 100;
- self.items = self.items | IT_AXE | IT_SHOTGUN | IT_SUPER_SHOTGUN |
- IT_NAILGUN | IT_SUPER_NAILGUN | IT_GRENADE_LAUNCHER |
- IT_ROCKET_LAUNCHER | IT_LIGHTNING;
-
- // support for item_key_custom -- iw
- base_item_key::give_all_keys (self);
-
- self.weapon = IT_ROCKET_LAUNCHER;
- self.impulse = 0;
- PlayerSetCurrentAmmo ();
-};
-
-//----------------------------------------------------------------------
-void() QuadCheat =
-{
- // 1998-07-29 Cheats coop fix by Maddes start
- // if (deathmatch || coop)
- if (deathmatch)
- // 1998-07-29 Cheats coop fix by Maddes end
- return;
-
- self.super_time = 1;
- self.super_damage_finished = time + 30;
- self.items = self.items | IT_QUAD;
- dprint ("quad cheat\n");
-};
-
-//----------------------------------------------------------------------
-// ServerflagsCommand -- Just for development
-//----------------------------------------------------------------------
-void() ServerflagsCommand =
-{
- // 1998-07-29 Cheats coop fix by Maddes start
- if (deathmatch)
- return;
- // 1998-07-29 Cheats coop fix by Maddes end
-
- serverflags = serverflags * 2 + 1;
-};
-
-//----------------------------------------------------------------------
-// ChangeWeaponCommand -- was W_ChangeWeapon
-//----------------------------------------------------------------------
-void() ChangeWeaponCommand =
-{
- local float it, haveammo, fl;
-
- // assign fl to silence a warning -- CEV
- fl = IT_AXE;
- it = self.items;
- haveammo = TRUE;
-
- switch (self.impulse)
- {
- case 1:
- fl = IT_AXE;
- break;
- case 2:
- fl = IT_SHOTGUN;
- if (self.ammo_shells < 1)
- haveammo = FALSE;
- break;
- case 3:
- fl = IT_SUPER_SHOTGUN;
- if (self.ammo_shells < 2)
- haveammo = FALSE;
- break;
- case 4:
- fl = IT_NAILGUN;
- if (self.ammo_nails < 1)
- haveammo = FALSE;
- break;
- case 5:
- fl = IT_SUPER_NAILGUN;
- if (self.ammo_nails < 2)
- haveammo = FALSE;
- break;
- case 6:
- fl = IT_GRENADE_LAUNCHER;
- if (self.ammo_rockets < 1)
- haveammo = FALSE;
- break;
- case 7:
- fl = IT_ROCKET_LAUNCHER;
- if (self.ammo_rockets < 1)
- haveammo = FALSE;
- break;
- case 8:
- fl = IT_LIGHTNING;
- if (self.ammo_cells < 1)
- haveammo = FALSE;
- break;
- default:
- dprint ("WARNING: W_ChangeWeapon: bad impulse: ");
- dprint (ftos (self.impulse));
- dprint ("\n");
- return;
- }
-
- self.impulse = 0;
-
- if (!(self.items & fl))
- { // don't have the weapon or the ammo
- sprint (self, "no weapon.\n");
- return;
- }
-
- if (haveammo == FALSE)
- { // don't have the ammo
- sprint (self, "not enough ammo.\n");
- return;
- }
-
- // set weapon, set ammo
- self.weapon = fl;
- PlayerSetCurrentAmmo ();
-};
-
-//----------------------------------------------------------------------
-// CycleWeaponCommand -- Go to the next weapon with ammo
-//----------------------------------------------------------------------
-void() CycleWeaponCommand =
-{
- local float haveammo;
-
- self.impulse = 0;
-
- while (1)
- {
- haveammo = TRUE;
-
- if (self.weapon == IT_LIGHTNING)
- {
- self.weapon = IT_AXE;
- }
- else if (self.weapon == IT_AXE)
- {
- self.weapon = IT_SHOTGUN;
- if (self.ammo_shells < 1)
- haveammo = FALSE;
- }
- else if (self.weapon == IT_SHOTGUN)
- {
- self.weapon = IT_SUPER_SHOTGUN;
- if (self.ammo_shells < 2)
- haveammo = FALSE;
- }
- else if (self.weapon == IT_SUPER_SHOTGUN)
- {
- self.weapon = IT_NAILGUN;
- if (self.ammo_nails < 1)
- haveammo = FALSE;
- }
- else if (self.weapon == IT_NAILGUN)
- {
- self.weapon = IT_SUPER_NAILGUN;
- if (self.ammo_nails < 2)
- haveammo = FALSE;
- }
- else if (self.weapon == IT_SUPER_NAILGUN)
- {
- self.weapon = IT_GRENADE_LAUNCHER;
- if (self.ammo_rockets < 1)
- haveammo = FALSE;
- }
- else if (self.weapon == IT_GRENADE_LAUNCHER)
- {
- self.weapon = IT_ROCKET_LAUNCHER;
- if (self.ammo_rockets < 1)
- haveammo = FALSE;
- }
- else if (self.weapon == IT_ROCKET_LAUNCHER)
- {
- self.weapon = IT_LIGHTNING;
- if (self.ammo_cells < 1)
- haveammo = FALSE;
- }
-
- if ((self.items & self.weapon) && haveammo == TRUE)
- {
- PlayerSetCurrentAmmo ();
- return;
- }
- }
-};
-
-//----------------------------------------------------------------------
-// CycleWeaponReverseCommand -- Go to the prev weapon with ammo
-//----------------------------------------------------------------------
-void() CycleWeaponReverseCommand =
-{
- local float haveammo;
-
- self.impulse = 0;
-
- while (1)
- {
- haveammo = TRUE;
-
- if (self.weapon == IT_LIGHTNING)
- {
- self.weapon = IT_ROCKET_LAUNCHER;
- if (self.ammo_rockets < 1)
- haveammo = FALSE;
- }
- else if (self.weapon == IT_ROCKET_LAUNCHER)
- {
- self.weapon = IT_GRENADE_LAUNCHER;
- if (self.ammo_rockets < 1)
- haveammo = FALSE;
- }
- else if (self.weapon == IT_GRENADE_LAUNCHER)
- {
- self.weapon = IT_SUPER_NAILGUN;
- if (self.ammo_nails < 2)
- haveammo = FALSE;
- }
- else if (self.weapon == IT_SUPER_NAILGUN)
- {
- self.weapon = IT_NAILGUN;
- if (self.ammo_nails < 1)
- haveammo = FALSE;
- }
- else if (self.weapon == IT_NAILGUN)
- {
- self.weapon = IT_SUPER_SHOTGUN;
- if (self.ammo_shells < 2)
- haveammo = FALSE;
- }
- else if (self.weapon == IT_SUPER_SHOTGUN)
- {
- self.weapon = IT_SHOTGUN;
- if (self.ammo_shells < 1)
- haveammo = FALSE;
- }
- else if (self.weapon == IT_SHOTGUN)
- {
- self.weapon = IT_AXE;
- }
- else if (self.weapon == IT_AXE)
- {
- self.weapon = IT_LIGHTNING;
- if (self.ammo_cells < 1)
- haveammo = FALSE;
- }
-
- if ((self.items & self.weapon) && haveammo == TRUE)
- {
- PlayerSetCurrentAmmo ();
- return;
- }
- }
-};
-
-//----------------------------------------------------------------------
-// ImpulseCommands
-//----------------------------------------------------------------------
-void() ImpulseCommands =
-{
- switch (self.impulse)
- {
- case 1..8:
- ChangeWeaponCommand ();
- return;
- case 9:
- CheatCommand ();
- break;
- case 10:
- CycleWeaponCommand ();
- break;
- case 11:
- ServerflagsCommand ();
- break;
- case 12:
- CycleWeaponReverseCommand ();
- break;
- case 100:
- // dumptruck_ds version inspired by Copper
- sprint (self, version);
- break;
- case 255:
- QuadCheat ();
- break;
- default:
- dprint (sprintf("ImpulseCommand: unknown impulse %g\n",
- self.impulse));
- break;
- }
-
- // debugging armor shards -- dumptruck_ds
- // if (self.impulse == 101)
- // dprint ("Armortype is");
- // dprint (ftos(self.armortype));
- // dprint ("\n");
-
- self.impulse = 0;
-};
Return to the top of this page or return to the overview of this repo.
Diff qc/client/intermission.qc
diff --git a/qc/client/intermission.qc b/qc/client/intermission.qc
deleted file mode 100644
index ece0575..0000000
--- a/qc/client/intermission.qc
+++ /dev/null
@@ -1,324 +0,0 @@
-//==============================================================================
-// intermission.qc -- LEVEL CHANGING / INTERMISSION
-//==============================================================================
-
-// globals
-float intermission_running;
-float intermission_exittime;
-entity used_exit;
-string nextmap;
-
-//----------------------------------------------------------------------
-void() info_intermissiontext =
-{
- if (self.message == "" || self.cnt == 0)
- {
- objerror ("endscreen lacks required fields");
- }
-};
-
-//----------------------------------------------------------------------
-void(string message) ShowIntermissionMessage =
-{
- WriteByte (MSG_ALL, SVC_FINALE);
- WriteString (MSG_ALL, message);
-};
-
-//----------------------------------------------------------------------
-void() StartMessageIntermission =
-{
- WriteByte (MSG_ALL, SVC_CDTRACK);
- WriteByte (MSG_ALL, 2);
- WriteByte (MSG_ALL, 3);
-};
-
-//----------------------------------------------------------------------
-void() Episode1End =
-{
- StartMessageIntermission ();
-
- if (!cvar("registered"))
- {
- ShowIntermissionMessage ("As the corpse of the monstrous "
- "entity\nChthon sinks back into the lava whence\n"
- "it rose, you grip the Rune of Earth\n"
- "Magic tightly. Now that you have\n"
- "conquered the Dimension of the Doomed,\n"
- "realm of Earth Magic, you are ready to\n"
- "complete your task in the other three\n"
- "haunted lands of Quake. Or are you? If\n"
- "you don't register Quake, you'll never\n"
- "know what awaits you in the Realm of\n"
- "Black Magic, the Netherworld, and the\nElder World!");
- }
- else
- {
- ShowIntermissionMessage ("As the corpse of the monstrous"
- "entity\nChthon sinks back into the lava whence\n"
- "it rose, you grip the Rune of Earth\n"
- "Magic tightly. Now that you have\n"
- "conquered the Dimension of the Doomed,\n"
- "realm of Earth Magic, you are ready to\n"
- "complete your task. A Rune of magic\n"
- "power lies at the end of each haunted\n"
- "land of Quake. Go forth, seek the\n"
- "totality of the four Runes!");
- }
-};
-
-//----------------------------------------------------------------------
-void() Episode2End =
-{
- StartMessageIntermission ();
-
- ShowIntermissionMessage ("The Rune of Black Magic throbs evilly in\n"
- "your hand and whispers dark thoughts\n"
- "into your brain. You learn the inmost\n"
- "lore of the Hell-Mother; Shub-Niggurath!\n"
- "You now know that she is behind all the\n"
- "terrible plotting which has led to so\n"
- "much death and horror. But she is not\n"
- "inviolate! Armed with this Rune, you\n"
- "realize that once all four Runes are\n"
- "combined, the gate to Shub-Niggurath's\n"
- "Pit will open, and you can face the\n"
- "Witch-Goddess herself in her frightful\n"
- "otherworld cathedral.");
-};
-
-//----------------------------------------------------------------------
-void() Episode3End =
-{
- StartMessageIntermission ();
-
- ShowIntermissionMessage ("The charred viscera of diabolic horrors\n"
- "bubble viscously as you seize the Rune\n"
- "of Hell Magic. Its heat scorches your\n"
- "hand, and its terrible secrets blight\n"
- "your mind. Gathering the shreds of your\n"
- "courage, you shake the devil's shackles\n"
- "from your soul, and become ever more\n"
- "hard and determined to destroy the\n"
- "hideous creatures whose mere existence\n"
- "threatens the souls and psyches of all\n"
- "the population of Earth.");
-
-};
-
-//----------------------------------------------------------------------
-void() Episode4End =
-{
- StartMessageIntermission ();
-
- ShowIntermissionMessage ("Despite the awful might of the Elder\n"
- "World, you have achieved the Rune of\n"
- "Elder Magic, capstone of all types of\n"
- "arcane wisdom. Beyond good and evil,\n"
- "beyond life and death, the Rune\n"
- "pulsates, heavy with import. Patient and\n"
- "potent, the Elder Being Shub-Niggurath\n"
- "weaves her dire plans to clear off all\n"
- "life from the Earth, and bring her own\n"
- "foul offspring to our world! For all the\n"
- "dwellers in these nightmare dimensions\n"
- "are her descendants! Once all Runes of\n"
- "magic power are united, the energy\n"
- "behind them will blast open the Gateway\n"
- "to Shub-Niggurath, and you can travel\n"
- "there to foil the Hell-Mother's plots\nin person.");
-};
-
-//----------------------------------------------------------------------
-float() RunId1Intermissions =
-{
- if (world.skip_id1_overrides == 0)
- {
- if (world.model == "maps/e1m7.bsp")
- {
- Episode1End ();
- return 1;
- }
- else if (world.model == "maps/e2m6.bsp")
- {
- Episode2End ();
- return 1;
- }
- else if (world.model == "maps/e3m6.bsp")
- {
- Episode3End ();
- return 1;
- }
- else if (world.model == "maps/e4m7.bsp")
- {
- Episode4End ();
- return 1;
- }
- }
- return 0;
-};
-
-//----------------------------------------------------------------------
-// FindIntermission -- Returns the entity to view from
-//----------------------------------------------------------------------
-entity() FindIntermission =
-{
- local entity spot;
- local float cyc;
-
- // look for info_intermission first
- spot = findfloat (world, classtype, CT_INFO_INTERMISSION);
- if (spot)
- { // pick a random one
- cyc = random() * 4;
- while (cyc > 1)
- {
- spot = findfloat (spot, classtype,
- CT_INFO_INTERMISSION);
- if (!spot)
- spot = findfloat (spot, classtype,
- CT_INFO_INTERMISSION);
- cyc = cyc - 1;
- }
- return spot;
- }
-
- // then look for the start position
- spot = find (world, classname, "info_player_start");
- if (spot)
- return spot;
-
- // testinfo_player_start is only found in regioned levels
- spot = find (world, classname, "testplayerstart");
- if (spot)
- return spot;
-
- objerror ("FindIntermission: no spot");
-
- // just to suppress the compiler warning
- return world;
-};
-
-//----------------------------------------------------------------------
-void() GotoNextMap =
-{
- if (cvar("samelevel"))
- // if samelevel is set, stay on same level
- changelevel (mapname);
- else
- changelevel (nextmap);
-};
-
-//----------------------------------------------------------------------
-float(float start) ShowIntermissionTextEntity =
-{
- if (!(used_exit.spawnflags & 2))
- {
- local entity end_message;
- for (end_message = world; (end_message = find
- (end_message, classname, "info_intermissiontext")); )
- {
- if (end_message.cnt == (intermission_running - 1))
- {
- if (start == 1)
- StartMessageIntermission ();
- ShowIntermissionMessage (end_message.message);
- return 1;
- }
- }
- }
- return 0;
-};
-
-//----------------------------------------------------------------------
-void() ExitIntermission =
-{
- // skip any text in deathmatch
- 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 (RunId1Intermissions() == 1)
- {
- return;
- }
- else
- {
- if (used_exit.message != "")
- {
- // favor message on changelevel
- StartMessageIntermission ();
- ShowIntermissionMessage (used_exit.message);
- return;
- }
- if (ShowIntermissionTextEntity(1))
- {
- 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 (ShowIntermissionTextEntity(0))
- {
- return;
- }
- if ((serverflags&15) == 15)
- {
- ShowIntermissionMessage ("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;
- }
- }
-
- if (intermission_running > 3)
- {
- if (ShowIntermissionTextEntity(0))
- {
- return;
- }
- }
-
- GotoNextMap ();
-};
-
-//----------------------------------------------------------------------
-// IntermissionThink -- When the player presses attack or jump, change
-// to the next level
-//----------------------------------------------------------------------
-void() IntermissionThink =
-{
- if (time < intermission_exittime)
- return;
-
- if (!self.button0 && !self.button1 && !self.button2)
- return;
-
- ExitIntermission ();
-};
Return to the top of this page or return to the overview of this repo.
Diff qc/client/levelparms.qc
diff --git a/qc/client/levelparms.qc b/qc/client/levelparms.qc
deleted file mode 100644
index 7ed4462..0000000
--- a/qc/client/levelparms.qc
+++ /dev/null
@@ -1,88 +0,0 @@
-//==============================================================================
-// client/levelparms.qc
-//==============================================================================
-
-//----------------------------------------------------------------------
-void() SetChangeParms =
-{
- if (self.health <= 0)
- {
- SetNewParms ();
- return;
- }
-
- // remove items
- self.items = self.items - (self.items &
- (IT_KEY1 | IT_KEY2 | IT_INVISIBILITY | IT_INVULNERABILITY
- | IT_SUIT | IT_QUAD)
- );
-
- // cap super health
- if (self.health > 100)
- self.health = 100;
- if (self.health < 50)
- self.health = 50;
- parm1 = self.items;
- parm2 = self.health;
- parm3 = self.armorvalue;
- if (self.ammo_shells < 25)
- parm4 = 25;
- else
- parm4 = self.ammo_shells;
- parm5 = self.ammo_nails;
- parm6 = self.ammo_rockets;
- parm7 = self.ammo_cells;
- parm8 = self.weapon;
- parm9 = self.armortype * 100;
-};
-
-//----------------------------------------------------------------------
-void() SetNewParms =
-{
- parm2 = 100; // self.health
- parm3 = 0; // self.armorvalue
- parm5 = 0; // self.ammo_nails
- parm6 = 0; // self.ammo_rockets
- parm7 = 0; // self.ammo_cells
- parm9 = 0; // self.armortype * 100
-
- // "reset_items 2" makes the player start with only the axe -- iw
- if (world.reset_items == 2)
- {
- parm1 = IT_AXE; // self.items
- parm4 = 0; // self.ammo_shells
- parm8 = IT_AXE; // self.weapon
- }
- else
- {
- parm1 = IT_AXE | IT_SHOTGUN; // self.items
- parm4 = 25; // self.ammo_shells
- parm8 = IT_SHOTGUN; // self.weapon
- }
-};
-
-//----------------------------------------------------------------------
-void() DecodeLevelParms =
-{
- // Reset the player's inventory if they returned to the start map
- // with a rune, or if the mapper set the "reset_items" field of
- // worldspawn to a non-zero value. (The old "reset_items" check,
- // which this replaces, had a comment from dumptruck_ds thanking
- // Spike.) -- iw
- if ((serverflags != 0 && world.model == "maps/start.bsp") ||
- world.reset_items != 0)
- {
- SetNewParms ();
- }
-
- self.items = parm1;
- self.health = parm2;
- self.armorvalue = parm3;
- self.ammo_shells = parm4;
- self.ammo_nails = parm5;
- self.ammo_rockets = parm6;
- self.ammo_cells = parm7;
- self.weapon = parm8;
- self.armortype = parm9 * 0.01;
-};
-
Return to the top of this page or return to the overview of this repo.
Diff qc/client/maprules.qc
diff --git a/qc/client/maprules.qc b/qc/client/maprules.qc
deleted file mode 100644
index 8391093..0000000
--- a/qc/client/maprules.qc
+++ /dev/null
@@ -1,92 +0,0 @@
-//==============================================================================
-// client/maprules.qc -- RULES
-//==============================================================================
-
-//----------------------------------------------------------------------
-// NextLevel -- go to the next level for deathmatch
-// only called if a time or frag limit has expired
-//----------------------------------------------------------------------
-void() NextLevel =
-{
- local trigger_changelevel t_level;
-
- 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;
- }
-
- t_level = spawn (trigger_changelevel, map:mapname);
- }
- else
- {
- // find a trigger changelevel
- local entity e;
- e = findfloat (world, classtype, CT_TRIGGER_CHANGELEVEL);
- t_level = (trigger_changelevel)e;
-
- // go back to start if no trigger_changelevel
- if (!t_level)
- t_level = spawn (trigger_changelevel, map:"start");
- }
-
- nextmap = t_level.map;
- gameover = TRUE;
-
- if (t_level.nextthink < time)
- {
- // TODO CEV
- // t_level.think = trigger_changelevel::changelevel_execute;
- t_level.nextthink = time + 0.1;
- }
-};
-
-//----------------------------------------------------------------------
-// CheckRules -- // Exit deathmatch games upon conditions
-//----------------------------------------------------------------------
-void() CheckRules =
-{
- local float fraglimit, timelimit;
-
- // someone else quit the game already
- if (gameover)
- return;
-
- timelimit = cvar ("timelimit") * 60;
- fraglimit = cvar ("fraglimit");
-
- // 1998-07-27 Timelimit/Fraglimit fix by Maddes
- if (deathmatch && timelimit && time >= timelimit)
- {
- NextLevel ();
- return;
- }
-
- // 1998-07-27 Timelimit/Fraglimit fix by Maddes
- if (deathmatch && fraglimit && self.frags >= fraglimit)
- {
- NextLevel ();
- return;
- }
-};
Return to the top of this page or return to the overview of this repo.
Diff qc/client/obituary.qc
diff --git a/qc/client/obituary.qc b/qc/client/obituary.qc
deleted file mode 100644
index 346b5e6..0000000
--- a/qc/client/obituary.qc
+++ /dev/null
@@ -1,336 +0,0 @@
-//==============================================================================
-// client/obituary.qc
-//==============================================================================
-
-//----------------------------------------------------------------------
-// ClientObituary -- called when a player dies
-//----------------------------------------------------------------------
-void(entity targ, entity inflictor, entity attacker) ClientObituary =
-{
- local float rnum;
- local string deathstring, deathstring2;
-
- rnum = random ();
- deathstring = deathstring2 = "";
-
- // refactored to remove one level of indentation -- CEV
- if (targ.classname != "player")
- return;
-
- 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;
- }
-
- if (attacker.classname == "teledeath2")
- {
- bprint ("Satan's power deflects ");
- bprint (targ.netname);
- bprint ("'s telefrag\n");
-
- targ.frags = targ.frags - 1;
- return;
- }
-
- // 1998-07-26 Pentagram telefrag fix by Zoid/Maddes start
- // double 666 telefrag
- // (can happen often in deathmatch 4 and levels with more
- // than one pentagram)
- if (attacker.classname == "teledeath3")
- {
- bprint (targ.netname);
- bprint (" was telefragged by ");
- bprint (attacker.owner.netname);
- bprint ("'s Satan's power\n");
- // 1998-07-26 only tfrag player on spot by Maddes start
- // targ.frags = targ.frags - 1;
- attacker.owner.frags = attacker.owner.frags + 1;
- // 1998-07-26 only tfrag player on spot by Maddes end
- return;
- }
-
- // 1998-07-26 Pentagram telefrag fix by Zoid/Maddes end
- if (attacker.classname == "player")
- {
- if (targ == attacker)
- {
- // killed self
- attacker.frags = attacker.frags - 1;
- bprint (targ.netname);
-
- if (targ.weapon == 64 &&
- targ.waterlevel > WATERLEVEL_FEET)
- {
- bprint (" discharges into the water.\n");
- return;
- }
- if (targ.weapon == IT_GRENADE_LAUNCHER)
- bprint (" tries to put the pin back in\n");
- else
- bprint (" becomes bored with life\n");
- return;
- }
- else if ((teamplay == 2) && (targ.team > 0) &&
- (targ.team == attacker.team))
- {
- 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 (attacker.netname);
- 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 > WATERLEVEL_FEET)
- 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);
-
- // custom obituary messages
- if (inflictor.deathtype != "")
- {
- bprint (" ");
- bprint (inflictor.deathtype);
- bprint ("\n");
- return;
- }
- if (attacker.deathtype != "")
- {
- bprint (" ");
- bprint (attacker.deathtype);
- bprint ("\n");
- return;
- }
-
- // killed by a monster?
- // if (attacker.flags & FL_MONSTER)
- if ((attacker.flags & FL_MONSTER) && (attacker.obit_name == ""))
- {
- if (attacker.classname == "monster_army")
- bprint (" was shot by a Grunt\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_dragon")
- bprint (" was fried by a Dragon\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_ogre_marksman")
- // dumptruck_ds
- bprint (" was felled by a Marksman\n");
- if (attacker.classname == "monster_oldone")
- bprint (" became one with Shub-Niggurath\n");
- if (attacker.classname == "monster_oldone2")
- // dumptruck_ds
- bprint (" became one with Shub-Niggurath\n");
- if (attacker.classname == "monster_boss2")
- // dumptruck_ds
- bprint (" was exploded by Chthon\n");
- if (attacker.classname == "monster_boss")
- // dumptruck_ds
- bprint (" was exploded by Chthon\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_vomit")
- bprint (" was vomited on by a Vomitus\n");
- if (attacker.classname == "monster_wizard")
- bprint (" was scragged by a Scrag\n");
- if (attacker.classname == "monster_zombie")
- bprint (" joins the Zombies\n");
-
- return;
- }
-
- // obits for custom monsters -- progs_dump -- dumptruck_ds
- if (attacker.obit_name != "")
- {
- bprint (" was ");
- if !(attacker.obit_method)
- bprint ("killed");
- else
- // e.g. ripped apart
- bprint (attacker.obit_method);
- bprint (" by ");
- // a bad monster
- bprint (attacker.obit_name);
- bprint ("\n");
- return;
- }
-
- // tricks and traps
- if (attacker.classname == "explo_box" ||
- attacker.classname == "play_explosion")
- {
- bprint (" blew up\n");
- return;
- }
- if (attacker.classname == "func_laser")
- {
- bprint (" discovered that lasers are hot\n");
- return;
- }
- if ((attacker.solid == SOLID_BSP &&
- attacker != world &&
- attacker.classname != "togglewall") ||
- (inflictor.classname == "func_movewall" &&
- !(inflictor.spawnflags & MOVEWALL_TOUCH)))
- {
- bprint (" was squished\n");
- return;
- }
- if (attacker.classname == "trap_shooter" ||
- attacker.classname == "trap_spikeshooter" ||
- attacker.classname == "trap_switched_shooter")
- {
- // bprint (" was spiked\n");
- // changed for custom shooters -- dumptruck_ds
- bprint (" was unlucky\n");
- return;
- }
- if (attacker.classname == "ltrail_start" ||
- attacker.classname == "ltrail_relay")
- {
- bprint (" had an electrifying experience\n");
- return;
- }
- if (attacker.classname == "fireball")
- {
- bprint (" ate a lavaball\n");
- return;
- }
- if (attacker.classname == "trigger_changelevel")
- {
- bprint (" tried to leave\n");
- return;
- }
-
- // in-liquid deaths
- if (targ.deathtype == "drowning")
- {
- if (random() < 0.5)
- bprint (" sleeps with the fishes\n");
- else
- bprint (" sucks it down\n");
- return;
- }
- if (targ.deathtype == "slime")
- {
- if (random() < 0.5)
- bprint (" gulped a load of slime\n");
- else
- bprint (" can't exist on slime alone\n");
- return;
- }
- if (targ.deathtype == "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")
- {
- bprint (" fell to his death\n");
- return;
- }
-
- // hell if I know; he's just dead!!!
- bprint (" died\n");
- }
-};
Return to the top of this page or return to the overview of this repo.
Diff qc/client/playerspawn.qc
diff --git a/qc/client/playerspawn.qc b/qc/client/playerspawn.qc
deleted file mode 100644
index fa73970..0000000
--- a/qc/client/playerspawn.qc
+++ /dev/null
@@ -1,359 +0,0 @@
-//==============================================================================
-// client/playerspawn.qc -- PLAYER GAME EDGE FUNCTIONS
-//==============================================================================
-
-// globals
-float modelindex_eyes, modelindex_player;
-
-// prototypes
-void() set_suicide_frame;
-void() DecodeLevelParms;
-void() PlayerDie;
-
-// 1998-09-16 Sliding/not-jumping on monsters/boxes/players fix by Maddes/Kryten start
-/*
-================
-by: Philip Martin aka: Kryten
-When on top of monsters or players you slide. This is a QuakeC problem.
-The function below fixes that problem.
-based on code given to Kryten by: Michael Turitzin (MaNiAc)
-================
-*/
-void() monster_touch =
-{
- //can cause problems for monsters on top of a player, so only players
- if (other.classname != "player")
- return;
- if (other.health <= 0)
- return;
-
- if ((!(other.flags & FL_ONGROUND)) &&
- ((other.absmin_z >= self.absmax_z - 2)))
- {
- other.flags = other.flags + FL_ONGROUND;
- }
-
- // you can add other stuff like pushable players/monsters here
-};
-// 1998-09-16 Sliding/not-jumping on monsters/boxes/players fix by Maddes/Kryten end
-
-
-//----------------------------------------------------------------------
-// respawn -- 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 =
-{
- // 1998-07-27 Suicide during intermission fix by Zhenga start
- // not allowed during intermission
- if ((intermission_running) && ((coop) || (deathmatch)))
- return;
- // 1998-07-27 Suicide during intermission fix by Zhenga end
- bprint (self.netname);
- bprint (" suicides\n");
- set_suicide_frame ();
- self.modelindex = modelindex_player;
- // extra penalty
- self.frags = self.frags - 2;
- respawn ();
-};
-
-//----------------------------------------------------------------------
-float(vector v) CheckSpawnPoint =
-{
- return FALSE;
-};
-
-//----------------------------------------------------------------------
-// SelectSpawnPoint -- Returns the entity to spawn at
-//----------------------------------------------------------------------
-entity() SelectSpawnPoint =
-{
- local entity spot, thing;
- local float pcount;
-
- // testinfo_player_start is only found in regioned levels
- spot = find (world, classname, "testplayerstart");
- if (spot)
- return spot;
-
- // choose a info_player_deathmatch point
- 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;
- // TODO CEV this loops infinitely if no info_player_deathmatch
- while (1)
- {
- spot = find (spot, classname, "info_player_deathmatch");
- if (spot != world)
- {
- 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;
- }
- }
- }
- }
-
- 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;
-};
-
-//----------------------------------------------------------------------
-// SendPlayer -- transmit player updates from server to client -- CEV
-//----------------------------------------------------------------------
-float(entity to, float fl) SendPlayer =
-{
- WriteByte (MSG_ENTITY, CT_PLAYER);
- WriteByte (MSG_ENTITY, self.frame);
- WriteCoord (MSG_ENTITY, self.origin_x);
- WriteCoord (MSG_ENTITY, self.origin_y);
- WriteCoord (MSG_ENTITY, self.origin_z);
- WriteShort (MSG_ENTITY, self.angles_x * 32767 / 360);
- WriteShort (MSG_ENTITY, self.angles_y * 32767 / 360);
- WriteShort (MSG_ENTITY, self.angles_z * 32767 / 360);
- WriteShort (MSG_ENTITY, self.velocity_x);
- WriteShort (MSG_ENTITY, self.velocity_y);
- WriteShort (MSG_ENTITY, self.velocity_z);
- WriteFloat (MSG_ENTITY, self.effects);
- WriteFloat (MSG_ENTITY, self.flags);
- WriteFloat (MSG_ENTITY, self.pmove_flags);
- WriteFloat (MSG_ENTITY, self.doublejump_timer);
- WriteFloat (MSG_ENTITY, self.groundboost_timer);
- return TRUE;
-};
-
-//----------------------------------------------------------------------
-// PutClientInServer -- called each time a player is spawned
-//----------------------------------------------------------------------
-void() PutClientInServer =
-{
- local entity spot;
-
- spot = SelectSpawnPoint ();
-
- self.classname = "player";
- self.classtype = CT_PLAYER;
- self.health = 100;
- self.takedamage = DAMAGE_AIM;
- self.solid = SOLID_SLIDEBOX;
- // self.solid = SOLID_BBOX;
- self.movetype = MOVETYPE_WALK;
- self.show_hostile = 0;
- self.max_health = 100;
- self.flags = FL_CLIENT;
- self.air_finished = time + 12;
- // initial water damage
- self.dmg = 2;
- self.super_damage_finished = 0;
- self.radsuit_finished = 0;
- self.invisible_finished = 0;
- self.invincible_finished = 0;
- self.effects = 0;
- self.invincible_time = 0;
- self.deathtype = "";
- self.gravity = 0;
- self.wantedgravity = 0;
- // support for item_key_custom -- iw
- self.customkeys = 0;
-
- // Setup cutscene stuff. Legacy code from Zerstorer. -- dumptruck_ds
- self.script_count = 2;
- self.script_delay = 1;
- self.script_time = 0;
-
- DecodeLevelParms ();
- PlayerSetCurrentAmmo ();
-
- self.attack_finished = time;
- self.th_pain = player_pain;
- self.th_die = PlayerDie;
- // 1998-09-16 Sliding/not-jumping on monsters/boxes/players fix
- // by Maddes/Kryten
- self.touch = monster_touch;
- self.deadflag = DEAD_NO;
- // pausetime is set by teleporters to keep the player from moving
- // for a while
- self.pausetime = 0;
-
- // spot = SelectSpawnPoint ();
-
- self.origin = spot.origin + '0 0 1';
- self.angles = spot.angles;
- // turn this way immediately
- self.fixangle = TRUE;
-
- // fog control.
- // Looks if there's any fog values set at the current spawn point.
- // If not, looks for those in worldspawn instead
- if (spot.fog_density)
- fog_save (self, spot.fog_density, spot.fog_color);
- else if (world.fog_density)
- fog_save (self, world.fog_density, world.fog_color);
-
- if (spot.skyfog_density)
- skyfog_save (self, spot.skyfog_density);
- else if (world.skyfog_density)
- skyfog_save (self, world.skyfog_density);
-
- // decreased on subsequent frames, used to start some fog-related stuff
- cleanUpClientStuff = 2;
-
- // oh, this is a hack!
- setmodel (self, "progs/eyes.mdl");
- modelindex_eyes = self.modelindex;
-
- // Drake -- dumptruck_ds
- setmodel (self, "progs/s_null.spr");
- // Drake -- dumptruck_ds
- // setmodel (self, "progs/null_256.spr");
- mindex_inviso = self.modelindex;
-
- setmodel (self, "progs/player.mdl");
- modelindex_player = self.modelindex;
-
- setsize (self, VEC_HULL_MIN, VEC_HULL_MAX);
-
- self.view_ofs = '0 0 22';
- // Mod - Xian (May.20.97)
- // Bug where player would have velocity from their last kill
- self.velocity = '0 0 0';
- // 1998-07-21 Player moves after respawn fix by Xian
-
- // TODO CEV
- self.SendEntity = SendPlayer;
- self.SendFlags = 0xffffff;
-
- player_stand1 ();
-
- if (deathmatch || coop)
- {
- makevectors (self.angles);
- spawn_tfog (self.origin + v_forward*20);
- }
-
- spawn_tdeath (self.origin, self);
-};
-
-//======================================================================
-// Player spawnpoint entities
-//======================================================================
-
-/*QUAKED info_player_start (1 0 0) (-16 -16 -24) (16 16 24) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-{
-model ("progs/player.mdl");
-}
-The normal starting point for a level.
-*/
-void() info_player_start =
-{
- // new spawnflags for all entities -- iw
- if (SUB_Inhibit())
- return;
-};
-
-/*QUAKED info_player_start2 (1 0 0) (-16 -16 -24) (16 16 24) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-{
-model ("progs/player.mdl");
-}
-Only used on start map for the return point from an episode.
-*/
-void() info_player_start2 =
-{
- // new spawnflags for all entities -- iw
- if (SUB_Inhibit())
- return;
-};
-
-//----------------------------------------------------------------------
-// testplayerstart -- saved out by quaked in region mode
-//----------------------------------------------------------------------
-void() testplayerstart =
-{
- // empty function
-};
-
-/*QUAKED info_player_coop (1 0 1) (-16 -16 -24) (16 16 24) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-{
-model ("progs/player.mdl");
-}
-potential spawning position for coop games
-*/
-void() info_player_coop =
-{
- // new spawnflags for all entities -- iw
- if (SUB_Inhibit())
- return;
-};
-
-/*QUAKED info_monster_spawnpoint (1 0 1) (-16 -16 -24) (16 16 24) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-{
-model ("progs/teleport.mdl");
-}
- spawning position for func_monster_spawner
-*/
-void() info_monster_spawnpoint =
-{
- // new spawnflags for all entities -- iw
- if (SUB_Inhibit())
- return;
-};
Return to the top of this page or return to the overview of this repo.
Diff qc/combat.qc
diff --git a/qc/combat.qc b/qc/combat.qc
deleted file mode 100644
index 3ea5650..0000000
--- a/qc/combat.qc
+++ /dev/null
@@ -1,464 +0,0 @@
-//==============================================================================
-
-// CEV: Contains the functions:
-//
-// CanDamage, Killed, T_Damage, T_RadiusDamage, T_BeamDamage
-
-/*
-============
-CanDamage
-
-Returns true if the inflictor can directly damage the target. 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,
- 0.5 * (targ.absmin + targ.absmax), 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 =
-{
- local entity oself;
-
- oself = self;
- self = targ;
-
- if (self.health < -99)
- // don't let sbar look bad if a player
- self.health = -99;
-
- if (self.movetype == MOVETYPE_PUSH || self.movetype == MOVETYPE_NONE)
- {
- // doors, triggers, etc
- if (targ.classtype == CT_FUNC_BREAKABLE)
- {
- local func_breakable fb = (func_breakable)targ;
- if (fb.th_die)
- fb.th_die ();
- }
- else
- {
- self.th_die ();
- }
- self = oself;
- return;
- }
-
- self.enemy = attacker;
-
- // bump the monster counter
- if (self.flags & FL_MONSTER)
- {
- killed_monsters = killed_monsters + 1;
- WriteByte (MSG_ALL, SVC_KILLEDMONSTER);
- }
-
- ClientObituary (self, inflictor, attacker);
-
- self.takedamage = DAMAGE_NO;
- self.touch = sub_null;
-
- // TODO CEV
- if (targ.classgroup & CG_MONSTER)
- {
- ((base_monster)targ).sub_death_use ();
- // monster_death_use ();
- }
-
- self.th_die ();
-
- self = oself;
-};
-
-/*
-============
-T_Damage
-
-The damage is coming from inflictor, but get mad at attacker
-This should be the only function that ever reduces health.
-============
-*/
-void(entity targ, entity inflictor, entity attacker, float damage) T_Damage=
-{
- local vector dir;
- local entity oldself;
- local float save;
- local float take;
- local float ignore_armor; //johnfitz
- local string death_type; //johnfitz
-
- // don't try to damage the world. Not healthy - bmFbr
- if (!targ)
- {
- return;
- }
-
- // make sure targ.deathtype doesn't keep stale info after
- // this function is done -- johnfitz
- death_type = targ.deathtype;
- targ.deathtype = "";
- // johnfitz
-
- if (!targ.takedamage)
- {
- return;
- }
-
- // some func_breakables ignore monster damage -- johnfitz
- // added from Rubicon2 combat.qc -- dumptruck_ds
- if (targ.classtype == CT_FUNC_BREAKABLE)
- {
- if (targ.spawnflags & BREAKABLE_NO_MONSTERS &&
- attacker.flags & FL_MONSTER)
- {
- return;
- }
- }
- // johnfitz
-
- // used by buttons and triggers to set activator for target firing
- damage_attacker = attacker;
-
- // check for quad damage powerup on the attacker
- if (attacker.super_damage_finished > time)
- damage = damage * 4;
-
- // damage mod for monsters -- dumptruck_ds
- if (attacker.damage_mod)
- damage = damage * attacker.damage_mod;
-
- // don't deplete armor if drowning/burning, or protected by
- // biosuit/pentagram/godmode (note: in ID1 pentagram/godmode
- // doesn't actually protect your armor)
- if (death_type == "burning" || death_type == "drowning" ||
- targ.invincible_finished >= time || targ.flags & FL_GODMODE)
- {
- ignore_armor = TRUE;
- }
- else
- {
- ignore_armor = FALSE;
- }
-
- // johnfitz
- // save damage based on the target's armor level
- if (ignore_armor)
- {
- // johnfitz -- some damage doesn't deplete armor
- save = 0;
- }
- else
- {
- save = ceil (targ.armortype * damage);
- if (save >= targ.armorvalue)
- {
- save = targ.armorvalue;
- // lost all armor
- targ.armortype = 0;
- targ.items = targ.items - (targ.items &
- (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3));
- }
- }
-
- // 1998-08-12 Drowning doesn't hurt armor by Maddes/Athos start
- // }
- // else
- // save = 0;
- // 1998-08-12 Drowning doesn't hurt armor by Maddes/Athos end
-
- targ.armorvalue = targ.armorvalue - save;
- take = ceil (damage - save);
-
- // add to the damage total for clients, which will be sent as a
- // single message at the end of the frame
- // FIXME: remove after combining shotgun blasts?
- if (targ.flags & FL_CLIENT)
- {
- targ.dmg_take = targ.dmg_take + take;
- targ.dmg_save = targ.dmg_save + save;
- targ.dmg_inflictor = inflictor;
- }
-
- // figure momentum add
- if ((inflictor != world) && (targ.movetype == MOVETYPE_WALK))
- {
- dir = targ.origin - (inflictor.absmin + inflictor.absmax) * 0.5;
- dir = normalize (dir);
- targ.velocity = targ.velocity + dir * damage * 8;
- }
-
- // check for godmode or invincibility
- if (targ.flags & FL_GODMODE)
- return;
-
- if (targ.invincible_finished >= time)
- {
- if (self.invincible_sound < time)
- {
- sound (targ, CHAN_ITEM, "items/protect3.wav",
- 1, ATTN_NORM);
- self.invincible_sound = time + 2;
- }
-
- return;
- }
-
- // team play damage avoidance
- // 1998-07-29 Teamplay 1 fix by Maddes start
- if ((teamplay == 1) && (targ.team > 0) &&
- (targ.team == attacker.team) && (targ != attacker) &&
- (attacker.classname == "player") &&
- (inflictor.classname != "door"))
- {
- // because squishing a teammate is still possible
- // 1998-07-29 Teamplay 1 fix by Maddes end
- return;
- }
-
- // do the damage
- targ.health = targ.health - take;
-
- // fire pain_target if appropriate
- if ((targ.flags & FL_MONSTER) &&
- targ.pain_target != "" &&
- targ.health <= targ.pain_threshold)
- {
- // TODO CEV
- /*
- oldself = self;
- self = targ;
- monster_pain_use ();
- self = oldself;
- */
- if (targ.classgroup & CG_MONSTER)
- {
- ((base_monster)targ).sub_pain_use ();
- }
- }
-
- if (targ.health <= 0)
- {
- Killed (targ, inflictor, attacker);
- return;
- }
-
- // react to the damage
- oldself = self;
- self = targ;
-
- if ((self.flags & FL_MONSTER) && attacker != world)
- {
- // get mad unless of the same class (except for soldiers)
- if (self != attacker && attacker != self.enemy)
- {
- local float mode;
- mode = 0;
-
- // take highest mode so infighting happens consistently
- if (self.infight_mode == -1 || self.infight_mode > mode)
- {
- mode = self.infight_mode;
- }
-
- if (mode != -1 && attacker.infight_mode > mode)
- {
- mode = attacker.infight_mode;
- }
-
- // soldiers of the same style will infight
- // -- dumptruck_ds
- //thanks for c0burn and Shamblernaut for your help!
- if (mode == -1)
- {
- if (attacker.classname == "player")
- {
- if (self.enemy.classname == "player")
- self.oldenemy = self.enemy;
- self.enemy = attacker;
- // TODO CEV
- if (self.classgroup & CG_MONSTER)
- {
- local base_monster m =
- (base_monster)self;
- dprint ("T_Damage: calling ai_foundtarget\n");
- m.ai_foundtarget ();
- }
- /*
- else
- {
- // TODO CEV
- FoundTarget ();
- }
- */
- }
- }
- else if ((self.classname != attacker.classname) ||
- ((self.classname == "monster_army") &&
- (self.style == attacker.style)) ||
- // infight if different models
- (mode > 0 &&
- self.mdl_body != attacker.mdl_body) ||
- // infight if different skin
- (mode > 1 &&
- self.skin != attacker.skin) ||
- // always infight
- (mode > 2))
- {
- if (self.enemy.classname == "player")
- self.oldenemy = self.enemy;
- self.enemy = attacker;
- // TODO CEV
- if (self.classgroup & CG_MONSTER)
- {
- local base_monster m1 =
- (base_monster)self;
- dprint ("T_Damage: calling ai_foundtarget\n");
- m1.ai_foundtarget ();
- }
- /*
- else
- {
- // TODO CEV
- FoundTarget ();
- }
- */
- }
- }
- }
-
- // TODO CEV
- if (self.classgroup & CG_MAPENTITY)
- {
- // cast to base_mapentity -- CEV
- // dprint (sprintf("T_Damage: calling do_damage on "
- // "mapentity %s\n", self.classname));
- local base_mapentity bme = (base_mapentity)self;
- bme.do_damage (attacker, take);
- }
- else
- {
- if (self.th_pain)
- {
- self.th_pain (attacker, take);
- // nightmare mode monsters don't go into pain
- // frames often
- if (skill == 3)
- self.pain_finished = time + 5;
- }
- }
-
- self = oldself;
-};
-
-/*
-============
-T_RadiusDamage
-============
-*/
-void(entity inflictor, entity attacker, float damage, entity ignore) T_RadiusDamage =
-{
- local float points;
- local entity head;
- local vector org;
-
- head = findradius(inflictor.origin, damage+40);
-
- while (head)
- {
- if (head != ignore)
- {
- if (head.takedamage)
- {
- org = head.origin + (head.mins + head.maxs)*0.5;
- points = 0.5*vlen (inflictor.origin - org);
- if (points < 0)
- points = 0;
- points = damage - points;
- if (head == attacker)
- points = points * 0.5;
- if (points > 0)
- {
- if (CanDamage (head, inflictor))
- { // shambler takes half damage from all explosions
- if (head.classname == "monster_shambler")
- T_Damage (head, inflictor, attacker, points*0.5);
- else
- T_Damage (head, inflictor, attacker, points);
- }
- }
- }
- }
- head = head.chain;
- }
-};
-
-/*
-============
-T_BeamDamage
-============
-*/
-void(entity attacker, float damage) T_BeamDamage =
-{
- local float points;
- local entity head;
-
- head = findradius(attacker.origin, damage+40);
-
- while (head)
- {
- if (head.takedamage)
- {
- points = 0.5*vlen (attacker.origin - head.origin);
- if (points < 0)
- points = 0;
- points = damage - points;
- if (head == attacker)
- points = points * 0.5;
- if (points > 0)
- {
- if (CanDamage (head, attacker))
- {
- if (head.classname == "monster_shambler")
- T_Damage (head, attacker, attacker, points*0.5);
- else
- T_Damage (head, attacker, attacker, points);
- }
- }
- }
- head = head.chain;
- }
-};
Return to the top of this page or return to the overview of this repo.
Diff qc/csqc/csqc_defsclient.qc
diff --git a/qc/csqc/csqc_defsclient.qc b/qc/csqc/csqc_defsclient.qc
index eab38d3..3f54f5c 100644
--- a/qc/csqc/csqc_defsclient.qc
+++ b/qc/csqc/csqc_defsclient.qc
@@ -79,14 +79,14 @@ vector pmove_error;
float pmove_errortime;
float pmove_frame;
-// imported from fteextensions.qc
-int trace_endcontents;
-int trace_surfaceflags;
-int trace_brush_id;
-int trace_brush_faceid;
-int trace_surface_id; // 1-based. 0 if not known.
-int trace_bone_id; // 1-based. 0 if not known.
-int trace_triangle_id; // 1-based. 0 if not known.
+// latched globals - re-set every StartFrame
+float frame_airstep;
+float frame_bigcoords;
+float frame_clrun;
+float frame_gravity;
+float frame_maxvelocity;
+float frame_nostep;
+float frame_standardphysics;
//----------------------------------------------------------------------
// Extra fields
Return to the top of this page or return to the overview of this repo.
Diff qc/csqc/csqc_hudvanilla.qc
diff --git a/qc/csqc/csqc_hudvanilla.qc b/qc/csqc/csqc_hudvanilla.qc
index cf4692d..4068808 100644
--- a/qc/csqc/csqc_hudvanilla.qc
+++ b/qc/csqc/csqc_hudvanilla.qc
@@ -816,15 +816,61 @@ void(vector virtmin, vector virtsize) Hud_Intermission =
);
};
+
+//======================================================================
+// Input Monitor -- CEV
+//----------------------------------------------------------------------
+void(vector pos) Hud_InputMonitor =
+{
+ if (input_movevalues_x)
+ if (input_movevalues_x < 0)
+ // backward
+ drawcharacter ([pos_x, pos_y, pos_z],
+ str2chr ("+", 0),
+ HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+ else if (input_movevalues_x > 0)
+ // forward
+ drawcharacter ([pos_x, pos_y - 8, pos_z],
+ str2chr ("^", 0),
+ HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+
+ if (input_movevalues_y)
+ if (input_movevalues_y < 0)
+ // left
+ drawcharacter ([pos_x - 12, pos_y, pos_z],
+ str2chr ("<", 0),
+ HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+ else if (input_movevalues_y > 0)
+ // right
+ drawcharacter ([pos_x + 12, pos_y, pos_z],
+ str2chr (">", 0),
+ HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+
+ if (input_movevalues_z)
+ if (input_movevalues_z < 0)
+ // down
+ drawcharacter ([pos_x - 38, pos_y, pos_z],
+ str2chr ("#", 0),
+ HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+ else if (input_movevalues_z > 0)
+ // up
+ drawcharacter ([pos_x - 24, pos_y, pos_z],
+ str2chr ("^", 0),
+ HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+
+ if (input_buttons & 0x00000002)
+ // INPUT_BUTTON2 jumping
+ drawcharacter ([pos_x - 24, pos_y, pos_z], str2chr ("^", 0),
+ HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+};
+
//======================================================================
// Speedometer -- CEV
//----------------------------------------------------------------------
void(vector pos) Hud_Speedometer =
{
- local vector v;
-
// fancy -- CEV
- v = [player_local.velocity_x, player_local.velocity_y, 0];
+ local vector v = [player_local.velocity_x, player_local.velocity_y, 0];
Hud_DrawNoFont8 (pos, rint(vlen(v)), 3, FALSE, HUDFONT_WHITE);
};
@@ -915,7 +961,11 @@ void(vector virtsize, float showscores) CSQC_DrawHud =
pos_speedo_x = virtsize_x / 2.0;
pos_speedo_y = virtsize_y / 2.0;
pos_speedo_z = 0;
- Hud_Speedometer (pos_speedo - [ 8 * 1.5, -8]);
+ Hud_Speedometer (pos_speedo - [8 * 1.5, -8]);
+
+ // Input Monitor TODO CEV
+ if (!cvar("crosshair"))
+ Hud_InputMonitor (pos_speedo - [4, 4, 0]);
if (hudviewsize < 120)
{
Return to the top of this page or return to the overview of this repo.
Diff qc/csqc/csqc_player.qc
diff --git a/qc/csqc/csqc_player.qc b/qc/csqc/csqc_player.qc
index e40527f..b969773 100644
--- a/qc/csqc/csqc_player.qc
+++ b/qc/csqc/csqc_player.qc
@@ -11,9 +11,7 @@
//======================================================================
// No-op function for customphysics
//----------------------------------------------------------------------
-void() Empty =
-{
-};
+void() sub_null = { };
//======================================================================
// PlayerResetPrediction
@@ -82,6 +80,15 @@ void(entity ent, float endframe) PlayerRunMovement =
ent.pmove_flags |= PMF_JUMP_HELD;
*/
+ // set all latched global variables now
+ frame_airstep = autocvar (pm_airstep, TRUE);
+ frame_bigcoords = autocvar (sv_bigcoords, FALSE);
+ frame_clrun = autocvar (cl_run, FALSE);
+ frame_gravity = autocvar (sv_gravity, 800.0);
+ frame_maxvelocity = autocvar (sv_maxvelocity, 10000.0);
+ frame_nostep = autocvar (pm_nostep, FALSE);
+ frame_standardphysics = autocvar (pm_standardphysics, FALSE);
+
while (pmove_frame <= endframe)
{
if (!getinputstate(pmove_frame))
@@ -91,7 +98,7 @@ void(entity ent, float endframe) PlayerRunMovement =
break;
}
- if (autocvar(pm_standardphysics, FALSE))
+ if (frame_standardphysics)
// for testing
runstandardplayerphysics (ent);
else
@@ -194,7 +201,7 @@ static void() PlayerRemove =
void() PlayerNew =
{
self.classname = "player";
- self.customphysics = Empty;
+ self.customphysics = sub_null;
// MASK_NORMAL ?
self.drawmask = MASK_ENGINE;
self.movetype = MOVETYPE_WALK;
@@ -232,6 +239,19 @@ void(float isnew) PlayerUpdate =
if (isnew && !(self.predraw))
PlayerNew ();
+ if (intermission)
+ {
+ // zero out velocity if in intermission -- CEV
+ frame_gravity = 0.0;
+ input_movevalues = '0 0 0';
+ self.velocity = '0 0 0';
+ viewentity.angles = self.angles;
+ viewentity.origin = self.origin;
+ setorigin (self, self.origin);
+ setorigin (viewentity, viewentity.origin);
+ return;
+ }
+
if (f != self.frame || isnew)
{
self.frame2 = self.frame;
@@ -253,10 +273,6 @@ void(float isnew) PlayerUpdate =
tempflags = self.flags;
pmflags = self.pmove_flags;
- if (intermission)
- // zero out velocity if in intermission -- CEV
- o = self.velocity = '0 0 0';
-
// PlayerRunMovement calls ResetPrediction -- CEV
// PlayerResetPrediction (self);
PlayerRunMovement (self, servercommandframe + 1);
Return to the top of this page or return to the overview of this repo.
Diff qc/csqc/csqc_progs.src
diff --git a/qc/csqc/csqc_progs.src b/qc/csqc/csqc_progs.src
index e17ac97..3da41be 100644
--- a/qc/csqc/csqc_progs.src
+++ b/qc/csqc/csqc_progs.src
@@ -19,7 +19,7 @@ csqc_defs.qc // from Sock's AD CSQC
//----------------------------------------------------------------------
// movement & client prediction, HUD, entity handling
//----------------------------------------------------------------------
-../player/pmove.qc // player movement code
+../pmove.qc // player movement code
csqc_player.qc // player handling
csqc_hudvanilla.qc // HUD
csqc_entrypoints.qc //
Return to the top of this page or return to the overview of this repo.
Diff qc/cutscene.qc
diff --git a/qc/cutscene.qc b/qc/cutscene.qc
index 998fedc..f5e7530 100644
--- a/qc/cutscene.qc
+++ b/qc/cutscene.qc
@@ -291,7 +291,8 @@ void() go_back =
c.movetype = MOVETYPE_WALK;
c.nextthink = time;
// PM: Reset player anim frames.
- c.think = player_run;
+ // TODO CEV
+ // c.think = player_run;
// No gasping from you!
more_air (c);
Return to the top of this page or return to the overview of this repo.
Diff qc/defs_builtins.qc
diff --git a/qc/defs_builtins.qc b/qc/defs_builtins.qc
index bb03db5..0bd0067 100644
--- a/qc/defs_builtins.qc
+++ b/qc/defs_builtins.qc
@@ -56,7 +56,7 @@ float(string s) cvar = #45; // return cvar.value
void(string s) localcmd = #46; // put string into local que
entity(entity e) nextent = #47; // for looping through all ents
void(vector o, vector d, float color, float count) particle = #48; // particles
-void() ChangeYaw = #49; // turn to ideal_yaw at yaw_speed
+void() changeyaw = #49; // turn to ideal_yaw at yaw_speed
// #50 was removed
vector(vector v) vectoangles = #51;
@@ -85,6 +85,8 @@ float(float angle) cos = #61;
// Part of DP_QC_SINCOSSQRTPOW
float(float value) sqrt = #62;
+void(entity ent, entity ignore) tracetoss = #64;
+
// Part of DP_QC_ETOS
string(entity ent) etos = #65;
Return to the top of this page or return to the overview of this repo.
Diff qc/defs_classtype.qc
diff --git a/qc/defs_classtype.qc b/qc/defs_classtype.qc
index 1e4cbcf..4fc2b34 100644
--- a/qc/defs_classtype.qc
+++ b/qc/defs_classtype.qc
@@ -16,18 +16,23 @@ enum
// monsters
CT_PLAYER, // player (client)
- // items & weapons
-
// info
CT_INFO_FOCAL_POINT, // cutscenes
CT_INFO_INTERMISSION, // id1, end-of-map camera position
+ CT_INFO_INTERMISSIONTEXT, // pd3? intermission text ent
+ CT_INFO_MONSTER_SPAWNPOINT, // pd3 monster spawnpoint
CT_INFO_MOVIE_CAMERA, // cutscenes
CT_INFO_NOTNULL, // id1?
CT_INFO_NULL, // id1?
+ CT_INFO_PLAYER_START, // id1 player start
+ CT_INFO_PLAYER_START2, // id1 player start2
+ CT_INFO_PLAYER_COOP, // id1 player coop start
+ CT_INFO_PLAYER_DEATHMATCH, // id1 player deathmatch start
CT_INFO_ROTATE, // Hipnotic info_rotate
CT_INFO_TELEPORT_CHANGEDEST, // Qmaster teleporter changedest
CT_INFO_TELEPORT_DESTINATION, // id1 teleporters
CT_INFO_TELEPORT_RANDOM, // teleporters
+ CT_INFO_TESTPLAYERSTART, // test player start
// func
CT_FUNC_BOB, // RennyC func_bob
@@ -189,6 +194,21 @@ enum
CT_PATH_CORNER, // id1 path_corner
CT_PATH_ROTATE, // Hipnotic rotation
+ // projectiles
+ CT_PROJECTILE_BULLET, // id1 shotgun pellets
+ CT_PROJECTILE_FLAK, // pd3 flak projectile
+ CT_PROJECTILE_GRENADE, // id1 grenade projectile
+ CT_PROJECTILE_HKNIGHT, // id1 hell / death knight magic
+ CT_PROJECTILE_LASERBEAM, // id1 laser projectile
+ CT_PROJECTILE_LAVABALL, // id1 lava balls (chthon projectile)
+ CT_PROJECTILE_MINIGRENADE, // DOE mini grenades
+ CT_PROJECTILE_MULTIGRENADE, // DOE multi grenades (spawns the mini)
+ CT_PROJECTILE_ROCKET, // id1 rocket projectile
+ CT_PROJECTILE_SPIKE, // id1 nail/spike projectile
+ CT_PROJECTILE_VOREBALL, // id1 vore projectile
+ CT_PROJECTILE_WIZARDMISSILE, // id1 Wizard (Scrag) missile
+ CT_PROJECTILE_ZOMBIECHUNK, // id1 zombie gib projectile
+
// targets
CT_TARGET_AUTOSAVE, // target_autosave from copper
CT_TARGET_FOGBLEND, // fog
@@ -241,16 +261,13 @@ enum
CT_TEMP_FALL2_HELPER, // RennyC & whirledtsar fall2
CT_TEMP_FIREBALL, // created by misc_fireball
CT_TEMP_FOG_CONTROLLER, // pd3 fog
- CT_TEMP_GRENADE, // id1 grenade projectile
CT_TEMP_KEYDEF, // pd3 custom key definition
- CT_TEMP_LASERBEAM, // id1 laser projectile
- CT_TEMP_ROCKET, // id1 rocket projectile
CT_TEMP_LASER_HELPER, // Rubicon2 func_laser
CT_TEMP_NEWPLAT_TRIGGER, // pd3 newplats
CT_TEMP_PLAT_TRIGGER, // id1 plats
CT_TEMP_ROTATE_CONTROLLER, // rotation controller
CT_TEMP_SPARK, // misc_sparks
- CT_TEMP_SPIKE // id1 nail/spike projectile
+ CT_TEMP_WIZARDSPELL // id1 wizard spell (spawns missiles)
};
//----------------------------------------------------------------------
Return to the top of this page or return to the overview of this repo.
Diff qc/defs_misc.qc
diff --git a/qc/defs_misc.qc b/qc/defs_misc.qc
index ff1db1d..362d1ca 100644
--- a/qc/defs_misc.qc
+++ b/qc/defs_misc.qc
@@ -210,36 +210,56 @@ const float EV_FUNCTION = 6;
const float EV_POINTER = 7;
const float EV_INTEGER = 8;
+// program-wide spawnflags
+const float SPAWN_SILENTLY = 2097152;
+const float TRIGGER_CENTERPRINTALL = 1048576;
+
+// traceline / tracebox flags from fteextensions.qc -- CEV
+const float MOVE_NORMAL = 0;
+// The trace will ignore all non-solid_bsp entities.
+const float MOVE_NOMONSTERS = 1;
+// The trace will use a bbox size of +/- 15 against entities with FL_MONSTER
+const float MOVE_MISSILE = 2;
+// Traces will impact the actual mesh of the model instead of merely their
+// bounding box. Should generally only be used for tracelines. Note that
+// this flag is unreliable as an object can animate through projectiles.
+// The bounding box MUST be set to completely encompass the entity or those
+// extra areas will be non-solid (leaving a hole for things to go through).
+const float MOVE_HITMODEL = 4;
+// This trace type will impact only triggers. It will ignore non-solid entities.
+const float MOVE_TRIGGERS = 16;
+// This type of trace will hit solids and triggers alike. Even non-solid
+// entities.
+const float MOVE_EVERYTHING = 32;
+
//======================================================================
// globals
//======================================================================
-float movedist;
-float gameover; // set when a rule exits
-string string_null; // null string
-// float empty_float;
+// latched globals - re-set every StartFrame
+float skill;
+float frame_airstep;
+float frame_bigcoords;
+float frame_clrun;
+float frame_gravity;
+float frame_maxvelocity;
+float frame_nostep;
+float frame_standardphysics;
+
+// per-map settings
+float known_release; // ID for a release, values above -- iw
-entity newmis; // set by launch_spike after spawning it
-entity activator; // entity that activated a trigger or
- // brush
-entity damage_attacker; // set by T_Damage
float framecount;
+float movedist;
+float gameover; // set when a rule exits
-float skill;
+entity activator; // entity that activated trigger/brush
+entity damage_attacker; // set by T_Damage
-float known_release; // unique ID for a release;
- // see values above -- iw
+nosave float cleanUpClientStuff;
+nosave float gamestarted;
-// imported from fteextensions.qc
-/*
-int trace_endcontents;
-int trace_surfaceflags;
-int trace_brush_id;
-int trace_brush_faceid;
-int trace_surface_id; // 1-based. 0 if not known.
-int trace_bone_id; // 1-based. 0 if not known.
-int trace_triangle_id; // 1-based. 0 if not known.
-*/
+string string_null; // null string
//======================================================================
// world fields (FIXME: make globals)
@@ -259,11 +279,7 @@ int trace_triangle_id; // 1-based. 0 if not known.
//======================================================================
// monster ai
//======================================================================
-.void() th_stand;
-.void() th_walk;
-.void() th_run;
-.void() th_missile;
-.void() th_melee;
+// TODO CEV rework into do_damage and do_destroy
.void(entity attacker, float damage) th_pain;
.void() th_die;
@@ -274,13 +290,6 @@ int trace_triangle_id; // 1-based. 0 if not known.
.float lefty;
.float search_time;
-.float attack_state;
-
-float AS_STRAIGHT = 1;
-float AS_SLIDING = 2;
-float AS_MELEE = 3;
-float AS_MISSILE = 4;
-float AS_TURRET = 5;
//======================================================================
// player only fields
@@ -335,11 +344,13 @@ float AS_TURRET = 5;
//======================================================================
.float pausetime;
.entity movetarget;
+.float infight_mode;
+
+// projectiles
.float homing;
.float projexpl;
.float proj_speed_mod;
.float proj_basespeed;
-.float infight_mode;
//======================================================================
// misc
@@ -349,7 +360,6 @@ float AS_TURRET = 5;
//======================================================================
// subs
//======================================================================
-.void() think1;
.vector finaldest, finalangle;
//======================================================================
@@ -454,9 +464,6 @@ nosave float *world_sounds; // via Spike fun times! nosave=noclobber
void() Cutscene_Think;
float cutscene; // Set to TRUE during a cutscene.
float mindex_inviso; // Invisible (null sprite)
-// .string null_string; // Replace 'string_null' with
- // 'world.null_string'. null string,
- // nothing should be held here.
// Custom Monster Sounds START -- dumptruck_ds
.string snd_death;
@@ -490,16 +497,10 @@ float mindex_inviso; // Invisible (null sprite)
.float drop_item; // key DropStuff
-const float SPAWN_SILENTLY = 2097152;
-const float TRIGGER_CENTERPRINTALL = 1048576;
-
// entity state
.float estate;
.float prevstate;
-nosave float cleanUpClientStuff;
-nosave float gamestarted;
-
.string include;
.string type;
@@ -507,11 +508,9 @@ nosave float gamestarted;
.entity last_setstate = aiment;
const float I_AM_TURRET = 262144; // dumptruck_ds
-.void() th_turret;
// TODO CEV
.vector cust_avelocity;
-.float touch_time;
// cshift controller
.entity csfcontroller;
Return to the top of this page or return to the overview of this repo.
Diff qc/entrypoints.qc
diff --git a/qc/entrypoints.qc b/qc/entrypoints.qc
new file mode 100644
index 0000000..1551e16
--- /dev/null
+++ b/qc/entrypoints.qc
@@ -0,0 +1,637 @@
+//==============================================================================
+// server-side entrypoints; inspired by Nuclide's server/entry.qc -- CEV
+//==============================================================================
+
+//======================================================================
+// globals
+//======================================================================
+float intermission_running;
+float intermission_exittime;
+entity used_exit;
+string nextmap;
+
+//======================================================================
+// Helper functions - map & game rules
+//======================================================================
+
+//----------------------------------------------------------------------
+// NextLevel -- go to the next level for deathmatch
+// only called if a time or frag limit has expired
+//----------------------------------------------------------------------
+void() NextLevel =
+{
+ local trigger_changelevel t_level;
+
+ 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;
+ }
+
+ t_level = spawn (trigger_changelevel, map:mapname);
+ }
+ else
+ {
+ // find a trigger changelevel
+ local entity e;
+ e = findfloat (world, classtype, CT_TRIGGER_CHANGELEVEL);
+ t_level = (trigger_changelevel)e;
+
+ // go back to start if no trigger_changelevel
+ if (!t_level)
+ t_level = spawn (trigger_changelevel, map:"start");
+ }
+
+ nextmap = t_level.map;
+ gameover = TRUE;
+
+ if (t_level.nextthink < time)
+ t_level.nextthink = time + 0.1;
+};
+
+//----------------------------------------------------------------------
+// CheckRules -- Exit deathmatch games upon conditions; 'self' is client
+//----------------------------------------------------------------------
+void() CheckRules =
+{
+ // someone else quit the game already
+ if (gameover)
+ return;
+
+ local float timelimit = cvar ("timelimit") * 60;
+ local float fraglimit = cvar ("fraglimit");
+
+ // 1998-07-27 Timelimit/Fraglimit fix by Maddes
+ if (deathmatch && timelimit && time >= timelimit)
+ {
+ NextLevel ();
+ return;
+ }
+
+ // 1998-07-27 Timelimit/Fraglimit fix by Maddes
+ if (deathmatch && fraglimit && self.frags >= fraglimit)
+ {
+ NextLevel ();
+ return;
+ }
+};
+
+//======================================================================
+// Helper functions - intermission handling
+//======================================================================
+
+//----------------------------------------------------------------------
+void(string message) ShowIntermissionMessage =
+{
+ WriteByte (MSG_ALL, SVC_FINALE);
+ WriteString (MSG_ALL, message);
+};
+
+//----------------------------------------------------------------------
+void() StartMessageIntermission =
+{
+ WriteByte (MSG_ALL, SVC_CDTRACK);
+ WriteByte (MSG_ALL, 2);
+ WriteByte (MSG_ALL, 3);
+};
+
+//----------------------------------------------------------------------
+void() Episode1End =
+{
+ StartMessageIntermission ();
+
+ if (!cvar("registered"))
+ {
+ ShowIntermissionMessage ("As the corpse of the monstrous "
+ "entity\nChthon sinks back into the lava whence\n"
+ "it rose, you grip the Rune of Earth\n"
+ "Magic tightly. Now that you have\n"
+ "conquered the Dimension of the Doomed,\n"
+ "realm of Earth Magic, you are ready to\n"
+ "complete your task in the other three\n"
+ "haunted lands of Quake. Or are you? If\n"
+ "you don't register Quake, you'll never\n"
+ "know what awaits you in the Realm of\n"
+ "Black Magic, the Netherworld, and the\nElder World!");
+ }
+ else
+ {
+ ShowIntermissionMessage ("As the corpse of the monstrous"
+ "entity\nChthon sinks back into the lava whence\n"
+ "it rose, you grip the Rune of Earth\n"
+ "Magic tightly. Now that you have\n"
+ "conquered the Dimension of the Doomed,\n"
+ "realm of Earth Magic, you are ready to\n"
+ "complete your task. A Rune of magic\n"
+ "power lies at the end of each haunted\n"
+ "land of Quake. Go forth, seek the\n"
+ "totality of the four Runes!");
+ }
+};
+
+//----------------------------------------------------------------------
+void() Episode2End =
+{
+ StartMessageIntermission ();
+
+ ShowIntermissionMessage ("The Rune of Black Magic throbs evilly in\n"
+ "your hand and whispers dark thoughts\n"
+ "into your brain. You learn the inmost\n"
+ "lore of the Hell-Mother; Shub-Niggurath!\n"
+ "You now know that she is behind all the\n"
+ "terrible plotting which has led to so\n"
+ "much death and horror. But she is not\n"
+ "inviolate! Armed with this Rune, you\n"
+ "realize that once all four Runes are\n"
+ "combined, the gate to Shub-Niggurath's\n"
+ "Pit will open, and you can face the\n"
+ "Witch-Goddess herself in her frightful\n"
+ "otherworld cathedral.");
+};
+
+//----------------------------------------------------------------------
+void() Episode3End =
+{
+ StartMessageIntermission ();
+
+ ShowIntermissionMessage ("The charred viscera of diabolic horrors\n"
+ "bubble viscously as you seize the Rune\n"
+ "of Hell Magic. Its heat scorches your\n"
+ "hand, and its terrible secrets blight\n"
+ "your mind. Gathering the shreds of your\n"
+ "courage, you shake the devil's shackles\n"
+ "from your soul, and become ever more\n"
+ "hard and determined to destroy the\n"
+ "hideous creatures whose mere existence\n"
+ "threatens the souls and psyches of all\n"
+ "the population of Earth.");
+
+};
+
+//----------------------------------------------------------------------
+void() Episode4End =
+{
+ StartMessageIntermission ();
+
+ ShowIntermissionMessage ("Despite the awful might of the Elder\n"
+ "World, you have achieved the Rune of\n"
+ "Elder Magic, capstone of all types of\n"
+ "arcane wisdom. Beyond good and evil,\n"
+ "beyond life and death, the Rune\n"
+ "pulsates, heavy with import. Patient and\n"
+ "potent, the Elder Being Shub-Niggurath\n"
+ "weaves her dire plans to clear off all\n"
+ "life from the Earth, and bring her own\n"
+ "foul offspring to our world! For all the\n"
+ "dwellers in these nightmare dimensions\n"
+ "are her descendants! Once all Runes of\n"
+ "magic power are united, the energy\n"
+ "behind them will blast open the Gateway\n"
+ "to Shub-Niggurath, and you can travel\n"
+ "there to foil the Hell-Mother's plots\nin person.");
+};
+
+//----------------------------------------------------------------------
+float() RunId1Intermissions =
+{
+ if (world.skip_id1_overrides == 0)
+ {
+ if (world.model == "maps/e1m7.bsp")
+ {
+ Episode1End ();
+ return 1;
+ }
+ else if (world.model == "maps/e2m6.bsp")
+ {
+ Episode2End ();
+ return 1;
+ }
+ else if (world.model == "maps/e3m6.bsp")
+ {
+ Episode3End ();
+ return 1;
+ }
+ else if (world.model == "maps/e4m7.bsp")
+ {
+ Episode4End ();
+ return 1;
+ }
+ }
+ return 0;
+};
+
+//----------------------------------------------------------------------
+// FindIntermission -- Returns the entity to view from
+//----------------------------------------------------------------------
+entity() FindIntermission =
+{
+ local entity spot;
+ local float cyc;
+
+ // look for info_intermission first
+ spot = findfloat (world, ::classtype, CT_INFO_INTERMISSION);
+ if (spot)
+ { // pick a random one
+ cyc = random() * 4;
+ while (cyc > 1)
+ {
+ spot = findfloat (spot, ::classtype,
+ CT_INFO_INTERMISSION);
+ if (!spot)
+ spot = findfloat (spot, ::classtype,
+ CT_INFO_INTERMISSION);
+ cyc = cyc - 1;
+ }
+ return spot;
+ }
+
+ // then look for the start position
+ spot = findfloat (world, classtype, CT_INFO_PLAYER_START);
+ if (spot)
+ return spot;
+
+ // testinfo_player_start is only found in regioned levels
+ spot = findfloat (world, classtype, CT_INFO_TESTPLAYERSTART);
+ if (spot)
+ return spot;
+
+ objerror ("FindIntermission: no spot");
+
+ // just to suppress the compiler warning
+ return world;
+};
+
+//----------------------------------------------------------------------
+void() GotoNextMap =
+{
+ if (cvar("samelevel"))
+ // if samelevel is set, stay on same level
+ changelevel (mapname);
+ else
+ changelevel (nextmap);
+};
+
+//----------------------------------------------------------------------
+float(float start) ShowIntermissionTextEntity =
+{
+ if (!(used_exit.spawnflags & 2))
+ {
+ local entity end_message;
+ for (end_message = world; (end_message = findfloat
+ (end_message, ::classtype, CT_INFO_INTERMISSIONTEXT)); )
+ {
+ if (end_message.cnt == (intermission_running - 1))
+ {
+ if (start == 1)
+ StartMessageIntermission ();
+ ShowIntermissionMessage (end_message.message);
+ return 1;
+ }
+ }
+ }
+ return 0;
+};
+
+//----------------------------------------------------------------------
+void() ExitIntermission =
+{
+ // skip any text in deathmatch
+ 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 (RunId1Intermissions() == 1)
+ {
+ return;
+ }
+ else
+ {
+ if (used_exit.message != "")
+ {
+ // favor message on changelevel
+ StartMessageIntermission ();
+ ShowIntermissionMessage (used_exit.message);
+ return;
+ }
+ if (ShowIntermissionTextEntity(1))
+ {
+ 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 (ShowIntermissionTextEntity(0))
+ {
+ return;
+ }
+ if ((serverflags&15) == 15)
+ {
+ ShowIntermissionMessage ("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;
+ }
+ }
+
+ if (intermission_running > 3)
+ {
+ if (ShowIntermissionTextEntity(0))
+ {
+ return;
+ }
+ }
+
+ GotoNextMap ();
+};
+
+//----------------------------------------------------------------------
+// IntermissionThink
+// When the player presses attack or jump, change to the next level
+// 'self' in this context is the client/player
+//----------------------------------------------------------------------
+void() IntermissionThink =
+{
+ // full send -- CEV
+ // self.fixangle = TRUE;
+ self.SendFlags = 0xffffff;
+
+ if (time < intermission_exittime)
+ return;
+
+ if (!self.button0 && !self.button1 && !self.button2)
+ return;
+
+ ExitIntermission ();
+};
+
+//======================================================================
+// REAL entrypoints (the following functions are called by the engine)
+//======================================================================
+
+//----------------------------------------------------------------------
+// ClientConnect
+// called when a player connects to a server; the client may not have
+// fully spawned yet (according to Nuclide's comments). self in this
+// context refers to the connecting client. -- CEV
+//----------------------------------------------------------------------
+void() ClientConnect =
+{
+ // a client connecting during an intermission can cause problems
+ if (intermission_running)
+ ExitIntermission ();
+
+ if (self.classname != "player")
+ // run the player spawn function, initializing 'self'
+ // as a player object -- CEV
+ spawnfunc_player ();
+
+ bprint (self.netname);
+ bprint (" entered the game\n");
+};
+
+//----------------------------------------------------------------------
+// ClientDisconnect
+// called when a player disconnects from a server; the client will be
+// removed after this function, so 'self' in this context is the player
+// and any fields of self can be accessed. -- CEV
+//----------------------------------------------------------------------
+void() ClientDisconnect =
+{
+ // if the level end trigger has been activated, just return
+ // since they aren't *really* leaving
+ if (gameover)
+ return;
+
+ // let everyone else know
+ bprint (self.netname);
+ bprint (" left the game with ");
+ bprint (ftos(self.frags));
+ bprint (" frags\n");
+ sound (self, CHAN_BODY, "player/tornoff2.wav", 1, ATTN_NONE);
+
+ if (self.classtype == CT_PLAYER)
+ ((player)self).set_suicide_frame ();
+ else
+ dprint ("ClientDisconnect: ERROR! Encountered a non-player!\n");
+};
+
+//----------------------------------------------------------------------
+// ClientKill -- Player entered the suicide command; 'self' is the client
+//----------------------------------------------------------------------
+void() ClientKill =
+{
+ // 1998-07-27 Suicide during intermission fix by Zhenga start
+ // not allowed during intermission
+ if ((intermission_running) && ((coop) || (deathmatch)))
+ return;
+ // 1998-07-27 Suicide during intermission fix by Zhenga end
+
+ bprint (self.netname);
+ bprint (" suicides\n");
+
+ if (self.classtype == CT_PLAYER)
+ {
+ ((player)self).set_suicide_frame ();
+ self.modelindex = modelindex_player;
+ // extra penalty
+ self.frags = self.frags - 2;
+ ((player)self).init_respawn ();
+ }
+ else
+ {
+ dprint ("ClientKill: ERROR! suicide from a non-player!\n");
+ }
+};
+
+//----------------------------------------------------------------------
+void() SetNewParms =
+{
+ parm2 = 100; // self.health
+ parm3 = 0; // self.armorvalue
+ parm5 = 0; // self.ammo_nails
+ parm6 = 0; // self.ammo_rockets
+ parm7 = 0; // self.ammo_cells
+ parm9 = 0; // self.armortype * 100
+
+ // "reset_items 2" makes the player start with only the axe -- iw
+ if (world.reset_items == 2)
+ {
+ parm1 = IT_AXE; // self.items
+ parm4 = 0; // self.ammo_shells
+ parm8 = IT_AXE; // self.weapon
+ }
+ else
+ {
+ parm1 = IT_AXE | IT_SHOTGUN; // self.items
+ parm4 = 25; // self.ammo_shells
+ parm8 = IT_SHOTGUN; // self.weapon
+ }
+};
+
+//----------------------------------------------------------------------
+void() SetChangeParms =
+{
+ if (self.health <= 0)
+ {
+ SetNewParms ();
+ return;
+ }
+
+ // remove items
+ self.items = self.items - (self.items &
+ (IT_KEY1 | IT_KEY2 | IT_INVISIBILITY | IT_INVULNERABILITY
+ | IT_SUIT | IT_QUAD)
+ );
+
+ // cap super health
+ if (self.health > 100)
+ self.health = 100;
+ if (self.health < 50)
+ self.health = 50;
+ parm1 = self.items;
+ parm2 = self.health;
+ parm3 = self.armorvalue;
+ if (self.ammo_shells < 25)
+ parm4 = 25;
+ else
+ parm4 = self.ammo_shells;
+ parm5 = self.ammo_nails;
+ parm6 = self.ammo_rockets;
+ parm7 = self.ammo_cells;
+ parm8 = self.weapon;
+ parm9 = self.armortype * 100;
+};
+
+//----------------------------------------------------------------------
+// PutClientInServer -- called each time a player is spawned
+// according to Nuclide: player has fully connected and loaded in.
+// 'self' is the player/client, parmX are populated with data carried
+// over from previous levels for this specific client. -- CEV
+//----------------------------------------------------------------------
+void() PutClientInServer =
+{
+ if (self.classname == "player")
+ dprint ("PutClientInServer: classname already player!\n");
+};
+
+//----------------------------------------------------------------------
+// PlayerPreThink -- Called every frame before physics are run
+//----------------------------------------------------------------------
+void() PlayerPreThink =
+{
+ if (intermission_running)
+ {
+ // otherwise a button could be missed between the think tics
+ IntermissionThink ();
+ return;
+ }
+
+ if (self.view_ofs == '0 0 0')
+ {
+ // Check for cutscene stuff.
+ Cutscene_Think ();
+ // intermission or finale
+ return;
+ }
+
+ // Check map / gametype rules, change to next level if requested -- CEV
+ CheckRules ();
+
+ // call prethink on the player after double checking classtype -- CEV
+ if (self.classtype == CT_PLAYER)
+ ((player)self).prethink ();
+};
+
+//----------------------------------------------------------------------
+// SV_RunClientCommand -- Called every frame to run physics
+//----------------------------------------------------------------------
+void() SV_RunClientCommand =
+{
+ // should match the one used by csqc.
+ if (frame_standardphysics)
+ // for testing -- CEV
+ runstandardplayerphysics (self);
+ else
+ // for real. See pmove.qc -- CEV
+ PM_Move (self);
+};
+
+//----------------------------------------------------------------------
+// PlayerPostThink -- Called every frame after physics are run
+//----------------------------------------------------------------------
+void() PlayerPostThink =
+{
+ if (intermission_running)
+ return;
+
+ // call postthink on the player after double checking classtype -- CEV
+ if (self.classtype == CT_PLAYER)
+ ((player)self).postthink ();
+};
+
+// TODO CEV based on code from Nuclide SDK
+/*
+void(void() spawnfunc) CheckSpawn =
+{
+ if (spawnfunc)
+ {
+ // dprint (sprintf("CheckSpawn: creating %s\n",
+ // self.classname));
+ spawnfunc ();
+ }
+ else
+ {
+ // print (sprintf("CheckSpawn: cannot find entity class %s\n",
+ // self.classname));
+ remove (self);
+ }
+};
+*/
Return to the top of this page or return to the overview of this repo.
Diff qc/fight.qc
diff --git a/qc/fight.qc b/qc/fight.qc
deleted file mode 100644
index b86bfd1..0000000
--- a/qc/fight.qc
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
-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 enemy_vis, enemy_infront, enemy_range, enemy_yaw;
-
-//============================================================================
-
-/*
-===========
-OgreCheckAttack
-
-The player is in view, so decide to move or launch an attack
-Returns FALSE if movement should continue
-============
-*/
-float() OgreCheckAttack =
-{
- local vector spot1, spot2;
- local entity targ;
- local float chance;
-
- // dprint("OgreCheckAttack\n");
- // dumptruck_ds
- if (self.spawnflags & I_AM_TURRET)
- {
- self.attack_state = AS_MISSILE;
- SUB_AttackFinished (2 + 2 * random());
- return TRUE;
- }
-
- 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;
-
- traceline (spot1, spot2, FALSE, self);
-
- if (trace_inopen && trace_inwater)
- // sight line crossed contents
- return FALSE;
-
- if ((self.spawnflags & I_AM_TURRET) && (trace_ent != targ))
- {
- // dprint("trace_ent...\n");
- self.attack_state = AS_TURRET;
- return FALSE;
- }
-
- if (trace_ent != targ)
- // don't have a clear shot
- return FALSE;
-
-
- // missile attack
- if (time < self.attack_finished)
- return FALSE;
-
- if (enemy_range == RANGE_FAR)
- return FALSE;
-
- else if (enemy_range == RANGE_NEAR)
- chance = 0.10;
- else if (enemy_range == RANGE_MID)
- chance = 0.05;
- else
- chance = 0;
-
- self.attack_state = AS_MISSILE;
- SUB_AttackFinished (1 + 2 * random());
- return TRUE;
-};
-
-//=============================================================================
-
-/*
-===========
-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 = '0 0 0';
- local vector spot2 = '0 0 0';
- local entity targ;
- local float chance;
-
- // dumptruck_ds
- if (self.spawnflags & I_AM_TURRET)
- {
- // dprint("CheckAttack...\n");
- if (self.classname == "monster_enforcer")
- {
- if (self.style == 4)
- {
- // lightning can only go so far
- if (vlen(spot1 - spot2) > 900)
- return FALSE;
- }
- self.attack_state = AS_MISSILE;
- }
- else if (self.classname == "monster_hell_knight")
- {
- if (self.style == 1)
- {
- // lightning can only go so far
- if (vlen(spot1 - spot2) > 900)
- return FALSE;
- }
- // self.attack_state = AS_MISSILE;
- self.th_turret ();
- }
- else if (self.classname == "monster_shalrath")
- {
- self.th_turret ();
- }
- /*
- else if (self.classname == "monster_zombie")
- {
- // dprint("CheckAttack...\n");
- // TODO CEV commented this out; this file to be deleted
- // zombie_turret_missile ();
- }
- */
- SUB_AttackFinished (2 * random());
- return TRUE;
- }
-
- 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 ((self.spawnflags & I_AM_TURRET) && (trace_ent != targ))
- {
- // dprint("trace_ent...\n");
- self.attack_state = AS_TURRET;
- return FALSE;
- }
-
- if (trace_inopen && trace_inwater)
- // sight line crossed contents
- return FALSE;
-
- if (trace_ent != targ)
- // don't have a clear shot
- return FALSE;
-
- if (enemy_range == RANGE_MELEE)
- {
- // melee attack
- if (self.th_melee)
- {
- // TODO CEV
- /*
- if (self.classname == "monster_knight")
- knight_attack ();
- else
- */
- 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 ();
-};
-
-/*
-=============
-ai_charge
-
-The monster is in a melee attack, so get as close as possible to .enemy
-=============
-*/
-void(float d) ai_charge =
-{
- ai_face ();
- // done in C code...
- movetogoal (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)
- // removed before stroke
- return;
-
- delta = self.enemy.origin - self.origin;
-
- if (vlen(delta) > 60)
- return;
-
- ldmg = (random() + random() + random()) * 3;
- T_Damage (self.enemy, self, self, ldmg);
-};
-
-void() ai_melee_side =
-{
- local vector delta;
- local float ldmg;
-
- if (!self.enemy)
- // removed before stroke
- return;
-
- 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;
- T_Damage (self.enemy, self, self, ldmg);
-};
Return to the top of this page or return to the overview of this repo.
Diff qc/func/breakable.qc
diff --git a/qc/func/breakable.qc b/qc/func/breakable.qc
index ba662a6..653dbf7 100644
--- a/qc/func/breakable.qc
+++ b/qc/func/breakable.qc
@@ -272,15 +272,17 @@ class base_breakable: base_func
make_breakable_debris ();
// to let us use noise2
- // TODO CEV
- func_explobox::explode_silent ();
+ // TODO CEV func_explobox::explode_silent ();
+ this.takedamage = DAMAGE_NO;
+ this.origin = ((this.absmin + this.absmax) * 0.5);
+ this.t_radiusdamage2 (this, this, this.dmg, world);
+ base_explosion::write_explosion (this.origin);
+ spawn (base_explosion, origin: this.origin);
// this is broken as of 1.1.0 no custom explosion
// sound for now -- dumptruck_ds
// sound (this, CHAN_VOICE, this.noise2, 1, ATTN_NORM);
- // explode_silent removes (this) already -- CEV
- if (this)
- remove (this);
+ remove (this);
}
else
{
@@ -307,7 +309,7 @@ class base_breakable: base_func
};
//--------------------------------------------------------------
- virtual void() breakable_killed =
+ virtual void() do_destroy =
{
activator = damage_attacker;
sub_usetargets ();
@@ -510,7 +512,7 @@ class func_breakable: base_breakable
if (this.targetname == __NULL__ || this.targetname == "")
{
this.takedamage = DAMAGE_YES;
- this.th_die = breakable_killed;
+ this.th_die = this.do_destroy;
}
if (this.switchshadstyle)
Return to the top of this page or return to the overview of this repo.
Diff qc/func/button.qc
diff --git a/qc/func/button.qc b/qc/func/button.qc
index ba03a5a..5eddda2 100644
--- a/qc/func/button.qc
+++ b/qc/func/button.qc
@@ -75,6 +75,20 @@ class func_button: base_func
};
//--------------------------------------------------------------
+ virtual void() do_destroy =
+ {
+ if (this.estate != STATE_ACTIVE)
+ return;
+
+ this.enemy = damage_attacker;
+ this.health = this.max_health;
+ // wil be reset upon return
+ this.takedamage = DAMAGE_NO;
+
+ button_fire ();
+ };
+
+ //--------------------------------------------------------------
// was button_return -- CEV
//--------------------------------------------------------------
virtual void() do_think =
@@ -113,20 +127,6 @@ class func_button: base_func
};
//--------------------------------------------------------------
- nonvirtual void() button_killed =
- {
- if (this.estate != STATE_ACTIVE)
- return;
-
- this.enemy = damage_attacker;
- this.health = this.max_health;
- // wil be reset upon return
- this.takedamage = DAMAGE_NO;
-
- button_fire ();
- };
-
- //--------------------------------------------------------------
// adapted from Copper, thanks Lunaran -- modified again by CEV
//--------------------------------------------------------------
nonvirtual void(func_button b) button_lock =
@@ -207,8 +207,8 @@ class func_button: base_func
if (this.health)
{
this.max_health = this.health;
- this.th_die = button_killed;
this.takedamage = DAMAGE_YES;
+ this.th_die = this.do_destroy;
}
if (!this.speed)
Return to the top of this page or return to the overview of this repo.
Diff qc/func/counter.qc
diff --git a/qc/func/counter.qc b/qc/func/counter.qc
index 21ee4d4..93f0060 100644
--- a/qc/func/counter.qc
+++ b/qc/func/counter.qc
@@ -65,7 +65,8 @@ class func_counter: base_func
//--------------------------------------------------------------
virtual void() do_think =
{
- if (this.spawnflags & COUNTER_START_ON && other != this)
+ if (this.spawnflags & COUNTER_START_ON && other != this &&
+ counter_on == TRUE)
{
// was counter_start_on_think -- CEV
// fix func_counter and func_oncount handling of
@@ -130,7 +131,8 @@ class func_counter: base_func
nonvirtual void() counter_off_use =
{
this.aflag = FALSE;
- if (this.spawnflags & COUNTER_TOGGLE)
+ // make sure to toggle -- CEV
+ if (this.spawnflags & COUNTER_TOGGLE || this.counter_on == TRUE)
{
this.counter_on = FALSE;
}
@@ -155,6 +157,8 @@ class func_counter: base_func
}
else
{
+ dprint ("func_counter::counter_off_use: calling "
+ "do_think...\n");
this.do_think ();
}
};
Return to the top of this page or return to the overview of this repo.
Diff qc/func/door.qc
diff --git a/qc/func/door.qc b/qc/func/door.qc
index bcee8f7..7f9519c 100644
--- a/qc/func/door.qc
+++ b/qc/func/door.qc
@@ -136,7 +136,7 @@ class func_door: base_func
//--------------------------------------------------------------
virtual void(entity blocker) do_blocked =
{
- T_Damage (blocker, this, this, this.dmg);
+ this.t_damage2 (blocker, this, this, this.dmg);
// if a door has a negative wait, it would never come back
// if blocked, so let it just squash the object to death
@@ -320,12 +320,12 @@ class func_door: base_func
};
//--------------------------------------------------------------
- virtual void() door_killed =
+ virtual void() do_destroy =
{
if (this.is_primary == FALSE)
{
if (prev_door && prev_door != this)
- prev_door.door_killed ();
+ prev_door.do_destroy ();
return;
}
@@ -751,7 +751,7 @@ class func_door: base_func
if (this.health)
{
this.takedamage = DAMAGE_YES;
- this.th_die = this.door_killed;
+ this.th_die = this.do_destroy;
}
if (this.spawnflags & DOOR_DOOM_STYLE_UNLOCK)
Return to the top of this page or return to the overview of this repo.
Diff qc/func/door_secret.qc
diff --git a/qc/func/door_secret.qc b/qc/func/door_secret.qc
index ab3df3f..7d7ba3b 100644
--- a/qc/func/door_secret.qc
+++ b/qc/func/door_secret.qc
@@ -39,7 +39,7 @@ class func_door_secret: base_func
return;
this.attack_finished = time + 0.5;
- T_Damage (blocker, this, this, this.dmg);
+ this.t_damage2 (blocker, this, this, this.dmg);
};
//--------------------------------------------------------------
@@ -50,6 +50,13 @@ class func_door_secret: base_func
};
//--------------------------------------------------------------
+ virtual void() do_destroy =
+ {
+ if (this.takedamage == DAMAGE_YES)
+ this.do_use (other);
+ };
+
+ //--------------------------------------------------------------
virtual void() do_think =
{
switch (this.door_state)
@@ -120,10 +127,10 @@ class func_door_secret: base_func
//--------------------------------------------------------------
// secret_touch - ouch; Prints messages
//--------------------------------------------------------------
- virtual void(entity t) do_touch =
+ virtual void(entity toucher) do_touch =
{
// from Copper -- dumptruck_ds
- if (sub_checkvalidtouch(t) == FALSE)
+ if (sub_checkvalidtouch(toucher) == FALSE)
return;
if (this.attack_finished > time)
@@ -133,8 +140,9 @@ class func_door_secret: base_func
if (this.message != "")
{
- centerprint (t, this.message);
- sound (t, CHAN_BODY, "misc/talk.wav", 1, ATTN_NORM);
+ centerprint (toucher, this.message);
+ sound (toucher, CHAN_BODY, "misc/talk.wav",
+ 1, ATTN_NORM);
}
};
@@ -241,7 +249,7 @@ class func_door_secret: base_func
{
this.health = 10000;
this.takedamage = DAMAGE_YES;
- this.th_die = this.use;
+ this.th_die = this.do_destroy;
}
this.oldorigin = this.origin;
Return to the top of this page or return to the overview of this repo.
Diff qc/func/elvtr_button.qc
diff --git a/qc/func/elvtr_button.qc b/qc/func/elvtr_button.qc
index 10662ee..ad9198a 100644
--- a/qc/func/elvtr_button.qc
+++ b/qc/func/elvtr_button.qc
@@ -96,6 +96,16 @@ class func_elvtr_button: base_func
};
//--------------------------------------------------------------
+ virtual void() do_destroy =
+ {
+ this.enemy = damage_attacker;
+ this.health = this.max_health;
+ // wil be reset upon return
+ this.takedamage = DAMAGE_NO;
+ elvtr_button_fire ();
+ };
+
+ //--------------------------------------------------------------
// was elvtr_button_return -- CEV
//--------------------------------------------------------------
virtual void() do_think =
@@ -130,16 +140,6 @@ class func_elvtr_button: base_func
};
//--------------------------------------------------------------
- nonvirtual void() elvtr_button_killed =
- {
- this.enemy = damage_attacker;
- this.health = this.max_health;
- // wil be reset upon return
- this.takedamage = DAMAGE_NO;
- elvtr_button_fire ();
- };
-
- //--------------------------------------------------------------
virtual void() init_spawned =
{
if (this.sounds == 0)
@@ -175,9 +175,8 @@ class func_elvtr_button: base_func
if (this.health)
{
this.max_health = this.health;
- // TODO CEV
- this.th_die = elvtr_button_killed;
this.takedamage = DAMAGE_YES;
+ this.th_die = this.do_destroy;
}
if (!this.speed)
Return to the top of this page or return to the overview of this repo.
Diff qc/func/explobox.qc
diff --git a/qc/func/explobox.qc b/qc/func/explobox.qc
index 33f0fae..e7fa7eb 100644
--- a/qc/func/explobox.qc
+++ b/qc/func/explobox.qc
@@ -21,20 +21,15 @@ class func_explobox: base_func
this.takedamage = DAMAGE_NO;
this.origin = ((this.absmin + this.absmax) * 0.5);
this.classname = "explo_box";
- T_RadiusDamage (this, this, this.dmg, world);
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, TE_EXPLOSION);
- WriteCoord (MSG_BROADCAST, this.origin_x);
- WriteCoord (MSG_BROADCAST, this.origin_y);
- WriteCoord (MSG_BROADCAST, this.origin_z);
+ this.t_radiusdamage2 (this, this, this.dmg, world);
+ base_explosion::write_explosion (this.origin);
// BecomeExplosion
spawn (base_explosion, origin: this.origin);
- if (this)
- remove (this);
+ remove (this);
};
//--------------------------------------------------------------
- nonvirtual void() explobox_die =
+ virtual void() do_destroy =
{
// for some reason, time + 0.2 doesn't work
this.nextthink = 0.2;
@@ -62,7 +57,7 @@ class func_explobox: base_func
this.dmg = 100;
// TODO CEV
- this.th_die = explobox_die;
+ this.th_die = this.do_destroy;
this.takedamage = DAMAGE_AIM;
};
Return to the top of this page or return to the overview of this repo.
Diff qc/func/fall.qc
diff --git a/qc/func/fall.qc b/qc/func/fall.qc
index ba934c8..9154c55 100644
--- a/qc/func/fall.qc
+++ b/qc/func/fall.qc
@@ -60,7 +60,7 @@ class func_fall: base_func
}
else if (toucher.flags & FL_MONSTER)
{
- T_Damage (toucher, this, toucher, 50000);
+ t_damage2 (toucher, this, toucher, 50000);
}
else
{
Return to the top of this page or return to the overview of this repo.
Diff qc/func/fall2.qc
diff --git a/qc/func/fall2.qc b/qc/func/fall2.qc
index 80b1f4e..4a35ec7 100644
--- a/qc/func/fall2.qc
+++ b/qc/func/fall2.qc
@@ -12,13 +12,14 @@ const float FALL2_BREAKABLE = 8; // VR
class temp_fall2_helper: base_tempentity
{
//--------------------------------------------------------------
- virtual void(entity e) do_touch =
+ virtual void(entity toucher) do_touch =
{
- if (e.flags & FL_FLY)
+ if (toucher.flags & FL_FLY)
// flying monsters shouldn't trigger falling platforms
return;
- if (e.flags & FL_MONSTER && owner.classtype == CT_FUNC_FALL2)
+ if (toucher.flags & FL_MONSTER &&
+ owner.classtype == CT_FUNC_FALL2)
{
dprint ("temp_fall2_helper: inside field_touch\n");
local func_fall2 ff2;
Return to the top of this page or return to the overview of this repo.
Diff qc/func/laser.qc
diff --git a/qc/func/laser.qc b/qc/func/laser.qc
index 5b76cc7..2db0e60 100644
--- a/qc/func/laser.qc
+++ b/qc/func/laser.qc
@@ -77,7 +77,7 @@ class func_laser: base_func
if (toucher.takedamage && this.attack_finished < time)
{
- T_Damage (toucher, this, this, this.dmg);
+ t_damage2 (toucher, this, this, this.dmg);
this.attack_finished = time + 0.1;
}
Return to the top of this page or return to the overview of this repo.
Diff qc/func/monster_spawner.qc
diff --git a/qc/func/monster_spawner.qc b/qc/func/monster_spawner.qc
index 39c06c0..aa988ef 100644
--- a/qc/func/monster_spawner.qc
+++ b/qc/func/monster_spawner.qc
@@ -82,452 +82,157 @@ class func_monster_spawner: base_func
};
//--------------------------------------------------------------
- nonvirtual void() create_mobot =
+ nonvirtual void(base_monster bot) create_mobot_tfrag =
{
- local entity bot, spawn_spot;
-
- // start entity and place it in world
- bot = spawn ();
- spawn_spot = find_spawnpoint ();
- // let's not use deathmatch points for this -- dumptruck_ds
- // spawn_spot = SelectSpawnPoint ();
- bot.origin = spawn_spot.origin + '0 0 1';
- bot.angles = spawn_spot.angles;
- bot.fixangle = TRUE;
- bot.proj_speed_mod = 1;
-
if (!(this.spawnflags & MOBOT_SILENT_SPAWN))
// SILENT
spawn_tfog (bot.origin);
spawn_tdeath (bot.origin, bot);
+ };
- if (this.style == 1)
- {
- // TODO CEV
- /*
- // spawn a Doggo
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel (bot, "progs/dog.mdl");
- setsize (bot, '-32 -32 -24', '32 32 40');
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = dog_stand1;
- bot.th_walk = dog_walk1;
- bot.th_run = dog_run1;
- bot.th_die = dog_die;
- bot.th_melee = dog_atta1;
- bot.th_missile = dog_leap1;
- // Berserk test from
- // celephais.net/board/view_thread.php?id=4&start=3465
- // -- dumptruck_ds
- if !(this.berserk)
- bot.th_pain = dog_pain;
- else
- bot.th_pain = sub_nullpain;
- bot.health = 25;
-
- // polish him up
- bot.classname = "monster_dog";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 22';
- */
- }
-
- if (this.style == 2)
- {
- // TODO CEV
- /*
- // spawn a Grunt
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel (bot, "progs/soldier.mdl");
- setsize (bot, '-16 -16 -24', '16 16 40');
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = army_stand1;
- bot.th_walk = army_walk1;
- bot.th_run = army_run1;
- bot.th_die = army_die;
- // bot.th_melee = ogre_melee;
- bot.th_missile = army_atk1;
- // Berserk test from
- // celephais.net/board/view_thread.php?id=4&start=3465
- // -- dumptruck_ds
- if !(this.berserk)
- bot.th_pain = army_pain;
- else
- bot.th_pain = sub_nullpain;
- bot.health = 80;
-
- // polish him up
- bot.classname = "monster_army";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 22';
- */
- }
-
- if (this.style == 3)
- {
- // TODO CEV
- /*
- // spawn an Enforcer
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel (bot, "progs/enforcer.mdl");
- setsize (bot, VEC_HULL2_MIN, VEC_HULL2_MAX);
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = enf_stand1;
- bot.th_walk = enf_walk1;
- bot.th_run = enf_run1;
- bot.th_die = enf_die;
- // bot.th_melee = ogre_melee;
- bot.th_missile = enf_atk1;
- // Berserk test from
- // celephais.net/board/view_thread.php?id=4&start=3465
- // -- dumptruck_ds
- if !(this.berserk)
- bot.th_pain = enf_pain;
- else
- bot.th_pain = sub_nullpain;
- bot.health = 80;
-
- // polish him up
- bot.classname = "monster_enforcer";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 22';
- */
- }
-
- if (this.style == 4)
- {
- // TODO CEV
- /*
- // spawn an Ogre
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel (bot, "progs/ogre.mdl");
- setsize (bot, VEC_HULL2_MIN, VEC_HULL2_MAX);
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = ogre_stand1;
- bot.th_walk = ogre_walk1;
- bot.th_run = ogre_run1;
- bot.th_die = ogre_die;
- bot.th_melee = ogre_melee;
- bot.th_missile = ogre_nail1;
- // Berserk test from
- // celephais.net/board/view_thread.php?id=4&start=3465
- // -- dumptruck_ds
- if !(this.berserk)
- bot.th_pain = ogre_pain;
- else
- bot.th_pain = sub_nullpain;
- bot.health = 200;
-
- // polish him up
- bot.classname = "monster_ogre";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 22';
- */
- }
-
- if (this.style == 5)
- {
- // TODO CEV
- /*
- // spawn an Fiend
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel (bot, "progs/demon.mdl");
- setsize (bot, VEC_HULL2_MIN, VEC_HULL2_MAX);
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = demon1_stand1;
- bot.th_walk = demon1_walk1;
- bot.th_run = demon1_run1;
- bot.th_die = demon_die;
- // one of two attacks
- bot.th_melee = Demon_MeleeAttack;
- // jump attack
- bot.th_missile = demon1_jump1;
- // Berserk test from
- // celephais.net/board/view_thread.php?id=4&start=3465
- // -- dumptruck_ds
- if !(this.berserk)
- bot.th_pain = demon1_pain;
- else
- bot.th_pain = sub_nullpain;
- bot.health = 300;
-
- // polish him up
- bot.classname = "monster_demon1";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 22';
- */
- }
-
- if (this.style == 6)
- {
- // TODO CEV
- /*
- // spawn a Wizard / Scrag
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel (bot, "progs/wizard.mdl");
- setsize (bot, '-16 -16 -24', '16 16 40');
- bot.flags = bot.flags | FL_FLY;
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = wiz_stand1;
- bot.th_walk = wiz_walk1;
- bot.th_run = wiz_run1;
- bot.th_die = wiz_die;
- bot.th_missile = Wiz_Missile;
- // Berserk test from
- // celephais.net/board/view_thread.php?id=4&start=3465
- // -- dumptruck_ds
- if !(this.berserk)
- bot.th_pain = Wiz_Pain;
- else
- bot.th_pain = sub_nullpain;
- bot.health = 80;
-
- // polish him up
- bot.classname = "monster_wizard";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 22';
- bot.mdl_proj = "progs/w_spike.mdl";
- */
- }
-
- if (this.style == 7)
- {
- // TODO CEV
- /*
- // spawn a Shambler
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel (bot, "progs/shambler.mdl");
- setsize (bot, '-16 -16 -24', '16 16 40');
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = sham_stand1;
- bot.th_walk = sham_walk1;
- bot.th_run = sham_run1;
- // Berserk test from
- // celephais.net/board/view_thread.php?id=4&start=3465
- // -- dumptruck_ds
- if !(this.berserk)
- bot.th_pain = sham_pain;
- else
- bot.th_pain = sub_nullpain;
- bot.th_die = sham_die;
- bot.th_missile = sham_magic1;
- bot.th_melee = sham_melee;
- bot.health = 600;
-
- // polish him up
- bot.classname = "monster_shambler";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 2';
- // bot.view_ofs = '0 0 22';
- */
- }
-
- if (this.style == 8)
- {
- // TODO CEV
- /*
- // spawn a Knight
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel (bot, "progs/knight.mdl");
- setsize (bot, '-16 -16 -24', '16 16 40');
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = knight_stand1;
- bot.th_walk = knight_walk1;
- bot.th_run = knight_run1;
- bot.th_die = knight_die;
- bot.th_melee = knight_atk1;
- // bot.th_missile = knight_atk1;
- // Berserk test from
- // celephais.net/board/view_thread.php?id=4&start=3465
- // -- dumptruck_ds
- if !(this.berserk)
- bot.th_pain = knight_pain;
- else
- bot.th_pain = sub_nullpain;
- bot.health = 75;
-
- // polish him up
- bot.classname = "monster_knight";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 22';
- */
- }
-
- if (this.style == 9)
- {
- // TODO CEV
- /*
- // spawn a HellKnight
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel (bot, "progs/hknight.mdl");
- setsize (bot, '-16 -16 -24', '16 16 40');
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = hknight_stand1;
- bot.th_walk = hknight_walk1;
- bot.th_run = hknight_run1;
- bot.th_melee = hknight_melee;
- bot.th_die = hknight_die;
- bot.th_missile = hknight_magicc1;
- // Berserk test from
- // celephais.net/board/view_thread.php?id=4&start=3465
- // -- dumptruck_ds
- if !(this.berserk)
- bot.th_pain = hknight_pain;
- else
- bot.th_pain = sub_nullpain;
- bot.health = 250;
-
- // polish him up
- bot.classname = "monster_hell_knight";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 22';
- */
- }
-
- if (this.style == 11)
- {
- // TODO CEV
- /*
- // spawn a Zombie
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel (bot, "progs/zombie.mdl");
- setsize (bot, '-16 -16 -24', '16 16 40');
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = zombie_start;
- bot.th_walk = zombie_walk1;
- bot.th_run = zombie_decide;
- bot.th_pain = zombie_pain;
- bot.th_die = zombie_die;
- bot.th_missile = zombie_missile;
- bot.health = 61;
-
- // polish him up
- bot.classname = "monster_zombie";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 2';
- // bot.view_ofs = '0 0 22';
- */
- }
-
- if (this.style == 12)
- {
- // TODO CEV
- /*
- // spawn a Shalrath
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel (bot, "progs/shalrath.mdl");
- setsize (bot, VEC_HULL2_MIN, VEC_HULL2_MAX);
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = shal_stand;
- bot.th_walk = shal_walk1;
- bot.th_run = shal_run1;
- bot.th_die = shalrath_die;
- bot.th_missile = shal_attack1;
- // fix for func_monster_spawner setting Voreballs
- // to non-homing
- bot.homing = 1;
- // Berserk test from
- // celephais.net/board/view_thread.php?id=4&start=3465
- // -- dumptruck_ds
- if !(this.berserk)
- bot.th_pain = shalrath_pain;
- else
- bot.th_pain = sub_nullpain;
- bot.health = 400;
-
- // polish him up
- bot.classname = "monster_shalrath";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 22';
- */
- }
-
- // TODO CEV
+ //--------------------------------------------------------------
+ nonvirtual void() create_mobot =
+ {
+ // let's not use deathmatch points for this -- dumptruck_ds
+ // spawn_spot = SelectSpawnPoint ();
+ local entity spawn_spot = find_spawnpoint ();
+ local float angry;
- /*
- // begin his thinking
- // this seems better with monster_use -- dumptruck_ds
- bot.nextthink = time + 0.2;
- // bot.nextthink = time + 0.1 + random();
- if (!(this.spawnflags & MOBOT_DONT_SPAWN_ANGRY))
- {
- // required to avoid animation issues -- dumptruck_ds
- if (bot.classname != "monster_zombie")
- bot.think = monster_use;
- else
- bot.think = bot.th_walk;
- }
+ if (this.spawnflags & MOBOT_DONT_SPAWN_ANGRY)
+ angry = FALSE;
else
+ angry = TRUE;
+
+ switch (this.style)
{
- bot.think = walkmonster_start_go;
+ case 1:
+ // spawn a Doggo
+ monster_dog bot1 = spawn (monster_dog,
+ origin: spawn_spot.origin + '0 0 1',
+ angles: spawn_spot.angles,
+ yaw_speed: 120,
+ spawn_angry: angry,
+ fixangle: TRUE,
+ view_ofs: '0 0 22');
+ create_mobot_tfrag (bot1);
+ break;
+ case 2:
+ // spawn a Grunt
+ monster_army bot2 = spawn (monster_army,
+ origin: spawn_spot.origin + '0 0 1',
+ angles: spawn_spot.angles,
+ yaw_speed: 120,
+ spawn_angry: angry,
+ fixangle: TRUE,
+ view_ofs: '0 0 22');
+ create_mobot_tfrag (bot2);
+ break;
+ case 3:
+ // spawn an Enforcer
+ monster_enforcer bot3 = spawn (monster_enforcer,
+ origin: spawn_spot.origin + '0 0 1',
+ angles: spawn_spot.angles,
+ yaw_speed: 120,
+ spawn_angry: angry,
+ fixangle: TRUE,
+ view_ofs: '0 0 22');
+ create_mobot_tfrag (bot3);
+ break;
+ case 4:
+ // spawn an Ogre
+ monster_ogre bot4 = spawn (monster_ogre,
+ origin: spawn_spot.origin + '0 0 1',
+ angles: spawn_spot.angles,
+ yaw_speed: 120,
+ spawn_angry: angry,
+ fixangle: TRUE,
+ view_ofs: '0 0 22');
+ create_mobot_tfrag (bot4);
+ break;
+ case 5:
+ // spawn a Fiend
+ monster_demon1 bot5 = spawn (monster_demon1,
+ origin: spawn_spot.origin + '0 0 1',
+ angles: spawn_spot.angles,
+ yaw_speed: 120,
+ spawn_angry: angry,
+ fixangle: TRUE,
+ view_ofs: '0 0 22');
+ create_mobot_tfrag (bot5);
+ break;
+ case 6:
+ // spawn a Wizard / Scrag
+ monster_wizard bot6 = spawn (monster_wizard,
+ origin: spawn_spot.origin + '0 0 1',
+ angles: spawn_spot.angles,
+ mdl_proj: "progs/w_spike.mdl",
+ yaw_speed: 120,
+ spawn_angry: angry,
+ fixangle: TRUE,
+ view_ofs: '0 0 22');
+ create_mobot_tfrag (bot6);
+ break;
+ case 7:
+ // spawn a Shambler
+ monster_shambler bot7 = spawn (monster_shambler,
+ origin: spawn_spot.origin + '0 0 1',
+ angles: spawn_spot.angles,
+ yaw_speed: 120,
+ spawn_angry: angry,
+ fixangle: TRUE,
+ view_ofs: '0 0 2');
+ create_mobot_tfrag (bot7);
+ break;
+ case 8:
+ // spawn a Knight
+ monster_knight bot8 = spawn (monster_knight,
+ origin: spawn_spot.origin + '0 0 1',
+ angles: spawn_spot.angles,
+ yaw_speed: 120,
+ spawn_angry: angry,
+ fixangle: TRUE,
+ view_ofs: '0 0 22');
+ create_mobot_tfrag (bot8);
+ break;
+ case 9:
+ // spawn a HellKnight
+ monster_hell_knight bot9 = spawn (
+ monster_hell_knight,
+ origin: spawn_spot.origin + '0 0 1',
+ angles: spawn_spot.angles,
+ yaw_speed: 120,
+ spawn_angry: angry,
+ fixangle: TRUE,
+ view_ofs: '0 0 22');
+ create_mobot_tfrag (bot9);
+ break;
+ case 11:
+ // spawn a Zombie
+ monster_zombie botB = spawn (monster_zombie,
+ origin: spawn_spot.origin + '0 0 1',
+ angles: spawn_spot.angles,
+ yaw_speed: 120,
+ spawn_angry: angry,
+ fixangle: TRUE,
+ view_ofs: '0 0 2');
+ create_mobot_tfrag (botB);
+ break;
+ case 12:
+ // spawn a Shalrath
+ monster_shalrath botC = spawn (monster_shalrath,
+ origin: spawn_spot.origin + '0 0 1',
+ angles: spawn_spot.angles,
+ yaw_speed: 120,
+ spawn_angry: angry,
+ fixangle: TRUE,
+ view_ofs: '0 0 22');
+ create_mobot_tfrag (botC);
+ break;
+ default:
+ dprint (sprintf("func_monster_spawner::"
+ "create_mobot: unknown style %g!\n",
+ this.style));
}
- */
if (!(this.spawnflags & MOBOT_DONT_ADD_KILL_COUNT))
{
Return to the top of this page or return to the overview of this repo.
Diff qc/func/new_plat.qc
diff --git a/qc/func/new_plat.qc b/qc/func/new_plat.qc
index b07221e..c3e5292 100644
--- a/qc/func/new_plat.qc
+++ b/qc/func/new_plat.qc
@@ -31,7 +31,7 @@ class temp_newplat_trigger: base_tempentity
return;
// at this point "this" is the trigger, "this.enemy" is
- // the plat, and "toucher" is the player.
+ // the plat, and "other" is the player.
// cast enemy to func_new_plat -- CEV
local func_new_plat fp = (func_new_plat)this.enemy;
@@ -66,13 +66,13 @@ class temp_newplat_trigger: base_tempentity
if (fp.state == FUNC_STATE_TOP)
{
otherState = FUNC_STATE_TOP;
- if (platPosition_z > toucher.origin_z)
+ if (platPosition_z > other.origin_z)
otherState = FUNC_STATE_BOTTOM;
}
else
{
otherState = FUNC_STATE_BOTTOM;
- if ((toucher.origin_z - platPosition_z) > fp.height)
+ if ((other.origin_z - platPosition_z) > fp.height)
otherState = FUNC_STATE_TOP;
}
@@ -206,7 +206,7 @@ class func_new_plat: base_func
//--------------------------------------------------------------
nonvirtual void(entity blocker) dn_and_wait_crush =
{
- T_Damage (blocker, this, this, 1);
+ this.t_damage2 (blocker, this, this, 1);
if (this.state == FUNC_STATE_UP)
dn_and_wait_go_down ();
@@ -262,7 +262,7 @@ class func_new_plat: base_func
//--------------------------------------------------------------
nonvirtual void(entity blocker) toggle_crush =
{
- T_Damage (blocker, this, this, 1);
+ this.t_damage2 (blocker, this, this, 1);
if (this.state == FUNC_STATE_UP)
toggle_go_down ();
@@ -519,7 +519,7 @@ class func_new_plat: base_func
//--------------------------------------------------------------
nonvirtual void(entity blocker) plat2_crush =
{
- T_Damage (blocker, this, this, 1);
+ this.t_damage2 (blocker, this, this, 1);
if (this.state == FUNC_STATE_UP)
plat2_go_down ();
Return to the top of this page or return to the overview of this repo.
Diff qc/func/particlefield.qc
diff --git a/qc/func/particlefield.qc b/qc/func/particlefield.qc
index 49ded3f..df16f34 100644
--- a/qc/func/particlefield.qc
+++ b/qc/func/particlefield.qc
@@ -183,7 +183,7 @@ class func_particlefield: base_func
return;
this.attack_finished = time + 0.5;
- T_Damage (toucher, this, this, this.dmg);
+ t_damage2 (toucher, this, this, this.dmg);
};
//--------------------------------------------------------------
Return to the top of this page or return to the overview of this repo.
Diff qc/func/plat.qc
diff --git a/qc/func/plat.qc b/qc/func/plat.qc
index b6593d2..ef1b6d6 100644
--- a/qc/func/plat.qc
+++ b/qc/func/plat.qc
@@ -32,10 +32,10 @@ class temp_plat_trigger: base_tempentity
//--------------------------------------------------------------
// this doesn't seem to be called from anywhere -- CEV
//--------------------------------------------------------------
- nonvirtual void(entity toucher) plat_outside_touch =
+ nonvirtual void() plat_outside_touch =
{
// from Copper -- dumptruck_ds
- if (sub_checkvalidtouch(toucher) == FALSE)
+ if (sub_checkvalidtouch(other) == FALSE)
return;
if (this.enemy.classtype != CT_FUNC_PLAT)
@@ -198,7 +198,7 @@ class func_plat: base_func
//--------------------------------------------------------------
virtual void(entity blocker) do_blocked =
{
- T_Damage (blocker, this, this, 1);
+ this.t_damage2 (blocker, this, this, 1);
if (this.state == FUNC_STATE_UP)
plat_go_down ();
Return to the top of this page or return to the overview of this repo.
Diff qc/func/rotate.qc
diff --git a/qc/func/rotate.qc b/qc/func/rotate.qc
index 5739eb8..ad22433 100644
--- a/qc/func/rotate.qc
+++ b/qc/func/rotate.qc
@@ -1056,12 +1056,12 @@ class func_movewall: base_rotate
if (this.dmg)
{
- T_Damage (toucher, this, this.owner, this.dmg);
+ t_damage2 (toucher, this, this.owner, this.dmg);
this.owner.attack_finished = time + 0.5;
}
else if (this.owner.dmg)
{
- T_Damage (toucher, this, this.owner, this.owner.dmg);
+ t_damage2 (toucher, this, this.owner, this.owner.dmg);
this.owner.attack_finished = time + 0.5;
}
};
@@ -1086,12 +1086,13 @@ class func_movewall: base_rotate
if (this.dmg)
{
- T_Damage (blocker, this, this.owner, this.dmg);
+ this.t_damage2 (blocker, this, this.owner, this.dmg);
this.owner.attack_finished = time + 0.5;
}
else if (this.owner.dmg)
{
- T_Damage (blocker, this, this.owner, this.owner.dmg);
+ this.t_damage2 (blocker, this, this.owner,
+ this.owner.dmg);
this.owner.attack_finished = time + 0.5;
}
};
Return to the top of this page or return to the overview of this repo.
Diff qc/func/togglewall.qc
diff --git a/qc/func/togglewall.qc b/qc/func/togglewall.qc
index b604e53..fd0f8d0 100644
--- a/qc/func/togglewall.qc
+++ b/qc/func/togglewall.qc
@@ -33,7 +33,7 @@ class func_togglewall: base_func
return;
this.attack_finished = time + 0.5;
- T_Damage (toucher, this, this, this.dmg);
+ t_damage2 (toucher, this, this, this.dmg);
sound (this, CHAN_VOICE, this.noise1, 1, ATTN_NORM);
};
Return to the top of this page or return to the overview of this repo.
Diff qc/func/train.qc
diff --git a/qc/func/train.qc b/qc/func/train.qc
index 6c52389..7a14969 100644
--- a/qc/func/train.qc
+++ b/qc/func/train.qc
@@ -43,7 +43,7 @@ class base_func_train: base_func
return;
this.attack_finished = time + 0.5;
- T_Damage (blocker, this, this, this.dmg);
+ this.t_damage2 (blocker, this, this, this.dmg);
};
//--------------------------------------------------------------
Return to the top of this page or return to the overview of this repo.
Diff qc/gore.qc
diff --git a/qc/gore.qc b/qc/gore.qc
new file mode 100644
index 0000000..4e2f9c4
--- /dev/null
+++ b/qc/gore.qc
@@ -0,0 +1,72 @@
+//==============================================================================
+// WEAPONS.QC
+//==============================================================================
+
+//----------------------------------------------------------------------
+vector() wall_velocity =
+{
+ local vector vel;
+
+ vel = normalize (self.velocity);
+ vel = normalize (vel + v_up*(random()- 0.5) +
+ v_right * (random() - 0.5));
+ vel = vel + 2 * trace_plane_normal;
+ vel = vel * 200;
+
+ return vel;
+};
+
+//----------------------------------------------------------------------
+// SpawnMeatSpray
+//----------------------------------------------------------------------
+void(vector org, vector vel) SpawnMeatSpray =
+{
+ local entity missile;
+
+ missile = spawn ();
+ missile.owner = self;
+ missile.movetype = MOVETYPE_BOUNCE;
+ missile.solid = SOLID_NOT;
+
+ makevectors (self.angles);
+
+ missile.velocity = vel;
+ missile.velocity_z = missile.velocity_z + 250 + 50 * random ();
+
+ missile.avelocity = '3000 1000 2000';
+
+ // set missile duration
+ missile.nextthink = time + 1;
+ missile.think = sub_remove;
+
+ setmodel (missile, "progs/zom_gib.mdl");
+ setsize (missile, '0 0 0', '0 0 0');
+ setorigin (missile, org);
+};
+
+//----------------------------------------------------------------------
+// SpawnBlood
+//----------------------------------------------------------------------
+void(vector org, vector vel, float damage) SpawnBlood =
+{
+ particle (org, vel * 0.1, 73, damage * 2);
+};
+
+//----------------------------------------------------------------------
+// spawn_touchblood
+//----------------------------------------------------------------------
+void(float damage) spawn_touchblood =
+{
+ local vector vel;
+
+ vel = wall_velocity() * 0.2;
+ SpawnBlood (self.origin + vel* 0.01, vel, damage);
+};
+
+//----------------------------------------------------------------------
+// SpawnChunk
+//----------------------------------------------------------------------
+void(vector org, vector vel) SpawnChunk =
+{
+ particle (org, vel * 0.02, 0, 10);
+};
Return to the top of this page or return to the overview of this repo.
Diff qc/hazards/ltrail.qc
diff --git a/qc/hazards/ltrail.qc b/qc/hazards/ltrail.qc
index 9062fb1..e956628 100644
--- a/qc/hazards/ltrail.qc
+++ b/qc/hazards/ltrail.qc
@@ -49,8 +49,8 @@ class base_hazard_ltrail: base_mapentity
WriteCoord (MSG_BROADCAST, targent.origin_x);
WriteCoord (MSG_BROADCAST, targent.origin_y);
WriteCoord (MSG_BROADCAST, targent.origin_z);
- LightningDamage (this.origin, targent.origin,
- this, this.currentammo);
+ weapon_lightning::lightning_damage (this.origin,
+ targent.origin, this, this.currentammo);
}
if (this.items < time)
Return to the top of this page or return to the overview of this repo.
Diff qc/hazards/shooter.qc
diff --git a/qc/hazards/shooter.qc b/qc/hazards/shooter.qc
index 8c13b7e..fd05744 100644
--- a/qc/hazards/shooter.qc
+++ b/qc/hazards/shooter.qc
@@ -14,60 +14,6 @@ const float SHOOTER_SPAWNFLAG_GRENADE = 32;
const float SHOOTER_SPAWNFLAG_GIBS = 64;
const float SHOOTER_SPAWNFLAG_SILENT = 128;
-//======================================================================
-// stray functions that need to be reworked -- TODO CEV
-//======================================================================
-
-//----------------------------------------------------------------------
-// ShalMissileTouch -- moved from Shalrath to enable shooter version
-//----------------------------------------------------------------------
-void() ShalMissileTouch =
-{
- if (other == self.owner)
- // don't explode on owner
- return;
-
- if (other.classname == "monster_zombie")
- T_Damage (other, self, self, 110);
-
- T_RadiusDamage (self, self.owner, 40, world);
- sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
-
- 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);
-
- // BecomeExplosion
- spawn (base_explosion, origin: self.origin);
- remove (self);
-};
-
-//----------------------------------------------------------------------
-// ZombieGrenadeTouch -- moved from zombie.qc to enable shooter version
-//----------------------------------------------------------------------
-void() ZombieGrenadeTouch =
-{
- if (other == self.owner)
- // don't explode on owner
- return;
-
- if (other.takedamage)
- {
- T_Damage (other, self, self.owner, 10 );
- sound (self, CHAN_WEAPON, "zombie/z_hit.wav", 1, ATTN_NORM);
- remove (self);
- return;
- }
-
- // bounce sound
- sound (self, CHAN_WEAPON, "zombie/z_miss.wav", 1, ATTN_NORM);
- self.velocity = '0 0 0';
- self.avelocity = '0 0 0';
- self.touch = sub_remove;
-};
-
//------------------------------------------------------------------------------
class base_hazard_shooter: base_mapentity
{
@@ -89,15 +35,29 @@ class base_hazard_shooter: base_mapentity
//--------------------------------------------------------------
virtual void(entity caller) do_use =
{
- local entity gnade, lavaball, rockettrap, voreball, zgibs;
-
if (this.spawnflags & SHOOTER_SPAWNFLAG_LASER)
{
if (!(this.spawnflags & SHOOTER_SPAWNFLAG_SILENT))
sound (this, CHAN_VOICE, "enforcer/enfire.wav",
1, ATTN_NORM);
- LaunchLaser (this.origin, this.movedir);
- newmis.spawnflags = this.spawnflags;
+
+ local vector laser_velocity = normalize (this.movedir);
+ // SetSpeed
+ laser_velocity *= min (LASER_SPEED * proj_speed_mod,
+ frame_maxvelocity);
+
+ // fire_laser
+ spawn (projectile_laser,
+ owner: this,
+ origin: this.origin,
+ velocity: laser_velocity,
+ homing: this.homing,
+ proj_speed_mod: this.proj_speed_mod,
+ snd_hit: this.snd_hit,
+ mdl_proj: this.mdl_proj,
+ skin_proj: this.skin_proj,
+ // why? -- CEV
+ spawnflags: this.spawnflags);
}
else if (this.spawnflags & SHOOTER_SPAWNFLAG_LAVABALL)
{
@@ -105,63 +65,57 @@ class base_hazard_shooter: base_mapentity
// dms
sound (this, CHAN_VOICE, "boss1/throw.wav",
1, ATTN_NORM);
- lavaball = spawn ();
- lavaball.movetype = MOVETYPE_FLYMISSILE;
- lavaball.solid = SOLID_BBOX;
- lavaball.classname = "lavaball";
- // set lavaball speed
- lavaball.velocity = this.movedir * 600; // was 300 dms
- lavaball.angles = vectoangles (lavaball.velocity);
- lavaball.owner = this;
- lavaball.touch = ShalMissileTouch;
- setmodel (lavaball, "progs/lavaball.mdl"); // dms
- setsize (lavaball, '0 0 0', '0 0 0');
- setorigin (lavaball, this.origin);
- lavaball.avelocity = '0 0 400';
- lavaball.nextthink = time + 5;
- lavaball.think = sub_remove;
+
+ spawn (projectile_lavaball,
+ owner: this,
+ origin: this.origin,
+ velocity: this.movedir * 600,
+ // custom spin of projectile - monster_shambler
+ avelocity: this.cust_avelocity,
+ // ShalMissileTouch
+ direct_damage: 40,
+ splash_damage: 40,
+ // homing parameters
+ homing: this.homing,
+ enemy: this.enemy,
+ proj_basespeed: 600,
+ proj_speed_mod: this.proj_speed_mod,
+ // custom model & skin
+ mdl_proj: this.mdl_proj,
+ skin_proj: this.skin_proj);
}
else if (this.spawnflags & SHOOTER_SPAWNFLAG_ROCKET)
{
if (!(this.spawnflags & SHOOTER_SPAWNFLAG_SILENT))
sound (this, CHAN_VOICE, "weapons/sgun1.wav",
1, ATTN_NORM);
- rockettrap = spawn ();
- rockettrap.movetype = MOVETYPE_FLYMISSILE;
- rockettrap.solid = SOLID_BBOX;
- rockettrap.classname = "rockettrap";
- // set rocket speed
- rockettrap.velocity = this.movedir * 1000;
- rockettrap.angles = vectoangles (rockettrap.velocity);
- rockettrap.owner = this;
- rockettrap.touch = T_MissileTouch;
- setmodel (rockettrap, "progs/missile.mdl"); // dms
- setsize (rockettrap, '0 0 0', '0 0 0');
- setorigin (rockettrap, this.origin);
- // rockettrap.avelocity = '0 0 400';
- rockettrap.nextthink = time + 5;
- rockettrap.think = sub_remove;
+
+ spawn (projectile_rocket,
+ owner: this,
+ origin: this.origin,
+ // set rocket speed
+ velocity: this.movedir * ROCKET_SPEED,
+ homing: this.homing,
+ enemy: this.enemy,
+ proj_basespeed: ROCKET_SPEED,
+ proj_speed_mod: this.proj_speed_mod,
+ // custom model & skin
+ mdl_proj: this.mdl_proj,
+ skin_proj: this.skin_proj);
}
else if (this.spawnflags & SHOOTER_SPAWNFLAG_VOREBALL)
{
if (!(this.spawnflags & SHOOTER_SPAWNFLAG_SILENT))
sound (this, CHAN_VOICE, "shalrath/attack2.wav",
1, ATTN_NORM);
- voreball = spawn ();
- voreball.movetype = MOVETYPE_FLYMISSILE;
- voreball.solid = SOLID_BBOX;
- voreball.classname = "voreball";
- // set voreball speed
- voreball.velocity = this.movedir * 600; // was 300 dms
- voreball.angles = vectoangles (voreball.velocity);
- voreball.owner = this;
- voreball.touch = ShalMissileTouch;
- setmodel (voreball, "progs/v_spike.mdl"); // dms
- setsize (voreball, '0 0 0', '0 0 0');
- setorigin (voreball, this.origin);
- voreball.avelocity = '0 0 400';
- voreball.nextthink = time + 5;
- voreball.think = sub_remove;
+
+ // note that we're not setting homing -- CEV
+ spawn (projectile_voreball,
+ owner: this,
+ origin: this.origin,
+ // was 300 (says dms), 600 in PD3 -- CEV
+ velocity: this.movedir * VOREBALL_SPEED,
+ avelocity: '0 0 400');
}
else if (this.spawnflags & SHOOTER_SPAWNFLAG_GRENADE)
{
@@ -171,50 +125,24 @@ class base_hazard_shooter: base_mapentity
local vector gnade_velocity = this.movedir * 600 +
v_up * 200 + crandom() * v_right * 10 +
crandom() * v_up * 10;
- gnade = spawn (projectile_grenade,
+ spawn (projectile_grenade,
owner: this,
origin: this.origin,
velocity: gnade_velocity);
- /*
- gnade.movetype = MOVETYPE_BOUNCE;
- // gnade.movetype = MOVETYPE_FLYMISSILE;
- gnade.solid = SOLID_BBOX;
- gnade.classname = "gnade";
- // set grenade speed
- // gnade.velocity = this.movedir * 600; // was 300 dms
- gnade.velocity = this.movedir * 600 + v_up * 200 +
- crandom() * v_right * 10 + crandom() * v_up * 10;
- gnade.angles = vectoangles (gnade.velocity);
- gnade.owner = this;
- gnade.touch = GrenadeTouch;
- setmodel (gnade, "progs/grenade.mdl"); // dms
- setsize (gnade, '0 0 0', '0 0 0');
- setorigin (gnade, this.origin);
- gnade.avelocity = '300 300 300';
- gnade.nextthink = time + 2.5;
- gnade.think = GrenadeExplode;
- */
}
else if (this.spawnflags & SHOOTER_SPAWNFLAG_GIBS)
{
if (!(this.spawnflags & SHOOTER_SPAWNFLAG_SILENT))
sound (this, CHAN_VOICE, "zombie/z_shot1.wav",
1, ATTN_NORM);
- zgibs = spawn ();
- zgibs.owner = this;
- zgibs.movetype = MOVETYPE_BOUNCE;
- zgibs.solid = SOLID_BBOX;
- zgibs.classname = "zgibs";
- setmodel (zgibs, "progs/zom_gib.mdl");
- setsize (zgibs, '0 0 0', '0 0 0');
- setorigin (zgibs, this.origin);
- zgibs.velocity = this.movedir * 600 + v_up * 200 +
- crandom() * v_right * 10 + crandom() * v_up * 10;
- zgibs.avelocity = '3000 1000 2000';
- zgibs.touch = ZombieGrenadeTouch;
- // set missile duration
- zgibs.nextthink = time + 2.5;
- zgibs.think = sub_remove;
+ local vector znade_velocity = this.movedir * 600 +
+ v_up * 200 + crandom() * v_right * 10 +
+ crandom() * v_up * 10;
+
+ spawn (projectile_zombiechunk,
+ owner: this,
+ origin: this.origin,
+ velocity: znade_velocity);
}
else
{
@@ -222,10 +150,31 @@ class base_hazard_shooter: base_mapentity
// changed vol fromt 1 to 0.666 -- CEV
sound (this, CHAN_VOICE, "weapons/spike2.wav",
0.666, ATTN_NORM);
- launch_spike (this.origin, this.movedir);
- newmis.velocity = this.movedir * 500;
+
+ local float damage;
+
if (this.spawnflags & SHOOTER_SPAWNFLAG_SUPERSPIKE)
- newmis.touch = superspike_touch;
+ damage = SPIKE_SUPER_DAMAGE;
+ else
+ damage = SPIKE_NORMAL_DAMAGE;
+
+ // shooter spikes move at half the speed of
+ // player spikes -- CEV
+ spawn (projectile_spike,
+ owner: this,
+ origin: this.origin,
+ velocity: this.movedir * 500,
+ direct_damage: damage,
+ // homing fields
+ homing: this.homing,
+ enemy: this.enemy,
+ proj_basespeed: 500,
+ proj_speed_mod: this.proj_speed_mod,
+ // model fields
+ mdl_proj: this.mdl_proj,
+ skin_proj: this.skin_proj,
+ // sound
+ snd_hit: this.snd_hit);
}
};
Return to the top of this page or return to the overview of this repo.
Diff qc/info/camera.qc
diff --git a/qc/info/camera.qc b/qc/info/camera.qc
index 94d8f54..e34777f 100644
--- a/qc/info/camera.qc
+++ b/qc/info/camera.qc
@@ -15,11 +15,11 @@ class info_movie_camera: base_mapentity
};
//--------------------------------------------------------------
- virtual void(entity e) do_touch =
+ virtual void(entity toucher) do_touch =
{
local string temps;
- if (other.classname != "camera")
+ if (toucher.classname != "camera")
return;
temps = this.target;
Return to the top of this page or return to the overview of this repo.
Diff qc/info/intermission.qc
diff --git a/qc/info/intermission.qc b/qc/info/intermission.qc
index 45de93b..06e69dc 100644
--- a/qc/info/intermission.qc
+++ b/qc/info/intermission.qc
@@ -16,3 +16,21 @@ class info_intermission: base_mapentity
};
};
+//----------------------------------------------------------------------
+class info_intermissiontext: base_mapentity
+{
+ //--------------------------------------------------------------
+ virtual void() init_spawned =
+ {
+ if (this.message == "" || this.cnt == 0)
+ {
+ objerror ("endscreen lacks required fields");
+ }
+ };
+
+ //--------------------------------------------------------------
+ void() info_intermissiontext =
+ {
+ this.classtype = CT_INFO_INTERMISSIONTEXT;
+ };
+};
Return to the top of this page or return to the overview of this repo.
Diff qc/info/path_corner.qc
diff --git a/qc/info/path_corner.qc b/qc/info/path_corner.qc
index 28dcbc5..e6769d3 100644
--- a/qc/info/path_corner.qc
+++ b/qc/info/path_corner.qc
@@ -61,7 +61,16 @@ void() t_movetarget =
if (!self.movetarget)
{
self.pausetime = time + 999999;
- self.th_stand ();
+ // TODO CEV
+ if (self.classgroup & CG_MONSTER)
+ {
+ ((base_monster)self).think_stand ();
+ }
+ else
+ {
+ dprint (sprintf("t_movetarget: ERROR tried to call "
+ "th_stand on classname %s!\n", self.classname));
+ }
return;
}
};
Return to the top of this page or return to the overview of this repo.
Diff qc/info/spawnpoints.qc
diff --git a/qc/info/spawnpoints.qc b/qc/info/spawnpoints.qc
new file mode 100644
index 0000000..648f486
--- /dev/null
+++ b/qc/info/spawnpoints.qc
@@ -0,0 +1,93 @@
+//======================================================================
+// Player & Monster spawnpoint entities
+//======================================================================
+
+/*QUAKED info_player_start (1 0 0) (-16 -16 -24) (16 16 24) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+{
+model ("progs/player.mdl");
+}
+The normal starting point for a level.
+*/
+class info_player_start: base_mapentity
+{
+ void() info_player_start =
+ {
+ this.classtype = CT_INFO_PLAYER_START;
+ };
+};
+
+/*QUAKED info_player_start2 (1 0 0) (-16 -16 -24) (16 16 24) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+{
+model ("progs/player.mdl");
+}
+Only used on start map for the return point from an episode.
+*/
+class info_player_start2: base_mapentity
+{
+ void() info_player_start2 =
+ {
+ this.classtype = CT_INFO_PLAYER_START2;
+ };
+};
+
+//----------------------------------------------------------------------
+// testplayerstart -- saved out by quaked in region mode
+//----------------------------------------------------------------------
+class testplayerstart: base_mapentity
+{
+ void() testplayerstart =
+ {
+ this.classtype = CT_INFO_TESTPLAYERSTART;
+ };
+};
+
+/*QUAKED info_player_coop (1 0 1) (-16 -16 -24) (16 16 24) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+{
+model ("progs/player.mdl");
+}
+potential spawning position for coop games
+*/
+class info_player_coop: base_mapentity
+{
+ void() info_player_coop =
+ {
+ this.classtype = CT_INFO_PLAYER_COOP;
+ };
+};
+
+/*QUAKED info_monster_spawnpoint (1 0 1) (-16 -16 -24) (16 16 24) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+{
+model ("progs/teleport.mdl");
+}
+ spawning position for func_monster_spawner
+*/
+class info_monster_spawnpoint: base_mapentity
+{
+ void() info_monster_spawnpoint =
+ {
+ this.classtype = CT_INFO_MONSTER_SPAWNPOINT;
+ };
+};
+
+/*QUAKED info_player_deathmatch (1 0 1) (-16 -16 -24) (16 16 24) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+{
+model ("progs/player.mdl");
+}
+potential spawning position for deathmatch games
+*/
+class info_player_deathmatch: base_mapentity
+{
+ virtual void() init_spawned =
+ {
+ this.alpha = 0.2;
+ this.model = "progs/player.mdl";
+ // $axstnd1 is 17.0 -- CEV
+ this.frame = 17.0;
+ setmodel (this, this.model);
+ };
+
+ void() info_player_deathmatch =
+ {
+ this.classtype = CT_INFO_PLAYER_DEATHMATCH;
+ };
+};
Return to the top of this page or return to the overview of this repo.
Diff qc/items/ammo.qc
diff --git a/qc/items/ammo.qc b/qc/items/ammo.qc
index f9665bd..e85a47c 100644
--- a/qc/items/ammo.qc
+++ b/qc/items/ammo.qc
@@ -62,11 +62,7 @@ class base_item_ammo: base_item
if (toucher.classtype == CT_PLAYER &&
autocvar(cg_autoswitch, TRUE))
{
- dprint ("base_item_ammo::do_touch: PlayerBestWeapon"
- "()\n");
- // TODO CEV
- best = REMOVEME_CallAsSelfFloat (other,
- PlayerBestWeapon);
+ ((player)toucher).best_weapon ();
}
// shotgun
@@ -112,21 +108,16 @@ class base_item_ammo: base_item
if (toucher.classtype == CT_PLAYER && toucher.weapon == best &&
autocvar(cg_autoswitch, TRUE))
{
- dprint ("base_item_ammo::do_touch: PlayerSetCurrentAmmo"
- "()\n");
// TODO CEV
- other.weapon = REMOVEME_CallAsSelfFloat (other,
- PlayerBestWeapon);
- REMOVEME_CallAsSelf (other, PlayerSetCurrentAmmo);
+ toucher.weapon = ((player)toucher).best_weapon ();
+ ((player)toucher).set_current_ammo ();
}
// if changed current ammo, update it
if (toucher.classtype == CT_PLAYER)
{
- dprint ("base_item_ammo::do_touch: PlayerSetCurrentAmmo"
- "()\n");
// TODO CEV
- REMOVEME_CallAsSelf (other, PlayerSetCurrentAmmo);
+ ((player)toucher).set_current_ammo ();
}
// remove it in single player, or setup for respawning in DM
Return to the top of this page or return to the overview of this repo.
Diff qc/items/armor.qc
diff --git a/qc/items/armor.qc b/qc/items/armor.qc
index 63fddb0..abc6bd6 100644
--- a/qc/items/armor.qc
+++ b/qc/items/armor.qc
@@ -220,54 +220,54 @@ class item_armor_shard: base_item_armor
local float bit;
- if ((other.items & IT_ARMOR1) || (other.items & IT_ARMOR2) ||
- (other.items & IT_ARMOR3))
+ if ((toucher.items & IT_ARMOR1) || (toucher.items & IT_ARMOR2)
+ || (toucher.items & IT_ARMOR3))
{
// has armor
// Supa, check bounds, original armourvalue + 25
- if (other.items & IT_ARMOR1 &&
- other.armorvalue >= ARMOR_GREEN_MAX)
+ if (toucher.items & IT_ARMOR1 &&
+ toucher.armorvalue >= ARMOR_GREEN_MAX)
{
return;
}
- if (other.items & IT_ARMOR2 &&
- other.armorvalue >= ARMOR_YELLOW_MAX)
+ if (toucher.items & IT_ARMOR2 &&
+ toucher.armorvalue >= ARMOR_YELLOW_MAX)
{
return;
}
- if (other.items & IT_ARMOR3 &&
- other.armorvalue >= ARMOR_RED_MAX)
+ if (toucher.items & IT_ARMOR3 &&
+ toucher.armorvalue >= ARMOR_RED_MAX)
{
return;
}
// was 2, RMQ team
- other.armorvalue = other.armorvalue + 5;
+ toucher.armorvalue = toucher.armorvalue + 5;
// Supa, now cap armourvalue to bounds
- if (other.items & IT_ARMOR1 &&
- other.armorvalue >= ARMOR_GREEN_MAX)
+ if (toucher.items & IT_ARMOR1 &&
+ toucher.armorvalue >= ARMOR_GREEN_MAX)
{
- other.armorvalue = ARMOR_GREEN_MAX;
+ toucher.armorvalue = ARMOR_GREEN_MAX;
}
- else if (other.items & IT_ARMOR2 &&
- other.armorvalue >= ARMOR_YELLOW_MAX)
+ else if (toucher.items & IT_ARMOR2 &&
+ toucher.armorvalue >= ARMOR_YELLOW_MAX)
{
- other.armorvalue = ARMOR_YELLOW_MAX;
+ toucher.armorvalue = ARMOR_YELLOW_MAX;
}
- else if (other.items & IT_ARMOR3 &&
- other.armorvalue >= ARMOR_RED_MAX)
+ else if (toucher.items & IT_ARMOR3 &&
+ toucher.armorvalue >= ARMOR_RED_MAX)
{
- other.armorvalue = ARMOR_RED_MAX;
+ toucher.armorvalue = ARMOR_RED_MAX;
}
}
else
{
// shard = Green armor level
- other.armortype = ARMOR_GREEN_ABSORB;
- other.armorvalue = ARMOR_SHARD_AMOUNT;
+ toucher.armortype = ARMOR_GREEN_ABSORB;
+ toucher.armorvalue = ARMOR_SHARD_AMOUNT;
bit = IT_ARMOR1;
- other.items = other.items - (other.items &
+ toucher.items = toucher.items - (toucher.items &
(IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)) + bit;
}
@@ -280,22 +280,22 @@ class item_armor_shard: base_item_armor
sprint (toucher, sprintf("You got %s\n",
this.obit_name));
else
- sprint(toucher, "You got armor\n");
+ sprint (toucher, "You got armor\n");
// armor touch sound
// dumptruck_ds custom models and sounds START
if (this.snd_misc != "")
- sound_misc (other, CHAN_AUTO, this.snd_misc,
+ sound_misc (toucher, CHAN_AUTO, this.snd_misc,
1, ATTN_NORM);
else
- sound_misc (other, CHAN_AUTO,"items/armor_shard_q3.wav",
- 1, ATTN_NORM);
+ sound_misc (toucher, CHAN_AUTO,
+ "items/armor_shard_q3.wav", 1, ATTN_NORM);
// dumptruck_ds custom models and sounds END
- stuffcmd (other, "bf\n");
+ stuffcmd (toucher, "bf\n");
// fire all targets / killtargets
- activator = other;
+ activator = toucher;
sub_usetargets ();
};
Return to the top of this page or return to the overview of this repo.
Diff qc/items/backpacks.qc
diff --git a/qc/items/backpacks.qc b/qc/items/backpacks.qc
index 041e45d..9b16e32 100644
--- a/qc/items/backpacks.qc
+++ b/qc/items/backpacks.qc
@@ -99,46 +99,45 @@ class item_backpack: base_item
local entity stemp;
// from Copper -- dumptruck_ds
- if (other.movetype == MOVETYPE_NOCLIP)
+ if (toucher.movetype == MOVETYPE_NOCLIP)
return;
- if (other.classtype != CT_PLAYER)
+ if (toucher.classtype != CT_PLAYER)
return;
- if (other.health <= 0)
+ if (toucher.health <= 0)
return;
acount = 0;
- sprint (other, "You get ");
+ sprint (toucher, "You get ");
if (this.items)
{
- if ((other.items & this.items) == 0)
+ if ((toucher.items & this.items) == 0)
{
acount = 1;
- sprint (other, "the ");
- sprint (other, this.netname);
+ sprint (toucher, "the ");
+ sprint (toucher, this.netname);
}
}
// if the player was using his best weapon, change
// up to the new one if better
- if (other.classtype == CT_PLAYER &&
+ if (toucher.classtype == CT_PLAYER &&
autocvar(cg_autoswitch, TRUE))
{
- best = REMOVEME_CallAsSelfFloat (other,
- PlayerBestWeapon);
+ best = ((player)toucher).best_weapon ();
}
// change weapons
- other.ammo_shells += this.ammo_shells;
- other.ammo_nails += this.ammo_nails;
- other.ammo_rockets += this.ammo_rockets;
- other.ammo_cells += this.ammo_cells;
+ toucher.ammo_shells += this.ammo_shells;
+ toucher.ammo_nails += this.ammo_nails;
+ toucher.ammo_rockets += this.ammo_rockets;
+ toucher.ammo_cells += this.ammo_cells;
new = this.items;
if (!new)
- new = other.weapon;
- old = other.items;
- other.items = other.items | new;
+ new = toucher.weapon;
+ old = toucher.items;
+ toucher.items = toucher.items | new;
bound_other_ammo ();
@@ -148,47 +147,47 @@ class item_backpack: base_item
if (this.ammo_shells)
{
if (acount)
- sprint (other, ", ");
+ sprint (toucher, ", ");
acount = 1;
s = ftos (this.ammo_shells);
- sprint (other, s);
- sprint (other, " shells");
+ sprint (toucher, s);
+ sprint (toucher, " shells");
}
if (this.ammo_nails)
{
if (acount)
- sprint (other, ", ");
+ sprint (toucher, ", ");
acount = 1;
s = ftos (this.ammo_nails);
- sprint (other, s);
- sprint (other, " nails");
+ sprint (toucher, s);
+ sprint (toucher, " nails");
}
if (this.ammo_rockets)
{
if (acount)
- sprint (other, ", ");
+ sprint (toucher, ", ");
acount = 1;
s = ftos (this.ammo_rockets);
- sprint (other, s);
- sprint (other, " rockets");
+ sprint (toucher, s);
+ sprint (toucher, " rockets");
}
if (this.ammo_cells)
{
if (acount)
- sprint (other, ", ");
+ sprint (toucher, ", ");
acount = 1;
s = ftos (this.ammo_cells);
- sprint (other, s);
- sprint (other, " cells");
+ sprint (toucher, s);
+ sprint (toucher, " cells");
}
- sprint (other, "\n");
+ sprint (toucher, "\n");
// backpack touch sound
- sound (other, CHAN_ITEM, "weapons/lock4.wav",
+ sound (toucher, CHAN_ITEM, "weapons/lock4.wav",
1, ATTN_NORM);
- stuffcmd (other, "bf\n");
+ stuffcmd (toucher, "bf\n");
- if (other.classtype == CT_PLAYER)
+ if (toucher.classtype == CT_PLAYER)
{
// change to the weapon
// 1997-12-23 Thunderbolt fix by Maddes start
@@ -207,8 +206,7 @@ class item_backpack: base_item
Deathmatch_Weapon (old, new);
PlayerSetCurrentAmmo ();
*/
- REMOVEME_CallAsSelf (other,
- PlayerSetCurrentAmmo);
+ ((player)toucher).set_current_ammo ();
}
// remove the backpack, change this to the player
@@ -217,35 +215,34 @@ class item_backpack: base_item
else
{
// item_backpack_message -- CEV
- other.ammo_shells += this.ammo_shells;
- other.ammo_nails += this.ammo_nails;
- other.ammo_rockets += this.ammo_rockets;
- other.ammo_cells += this.ammo_cells;
+ toucher.ammo_shells += this.ammo_shells;
+ toucher.ammo_nails += this.ammo_nails;
+ toucher.ammo_rockets += this.ammo_rockets;
+ toucher.ammo_cells += this.ammo_cells;
if (this.netname != "")
{
- sprint (other, "You got ");
- sprint (other, this.netname);
- sprint (other, "\n");
+ sprint (toucher, "You got ");
+ sprint (toucher, this.netname);
+ sprint (toucher, "\n");
}
else
{
- sprint (other, "You got a backpack!\n");
+ sprint (toucher, "You got a backpack!\n");
}
// backpack touch sound
- // sound (other, CHAN_ITEM, "weapons/lock4.wav",
+ // sound (toucher, CHAN_ITEM, "weapons/lock4.wav",
// 1, ATTN_NORM);
- sound_misc (other, CHAN_ITEM, this.snd_misc,
+ sound_misc (toucher, CHAN_ITEM, this.snd_misc,
1, ATTN_NORM);
remove (this);
- if (other.classtype == CT_PLAYER)
+ if (toucher.classtype == CT_PLAYER)
{
- stuffcmd (other, "bf\n");
+ stuffcmd (toucher, "bf\n");
bound_other_ammo ();
- REMOVEME_CallAsSelf (other,
- PlayerSetCurrentAmmo);
+ ((player)toucher).set_current_ammo ();
}
}
};
Return to the top of this page or return to the overview of this repo.
Diff qc/items/health.qc
diff --git a/qc/items/health.qc b/qc/items/health.qc
index 86ca373..dc5de94 100644
--- a/qc/items/health.qc
+++ b/qc/items/health.qc
@@ -77,25 +77,25 @@ class base_item_health: base_item
if (this.healtype == HEALTH_TYPE_MEGA)
{
// Megahealth? Ignore max_health...
- if (other.health >= 250)
+ if (toucher.health >= 250)
return;
- if (!T_Heal(other, amount, 1))
+ if (!T_Heal(toucher, amount, 1))
return;
}
else
{
- if (!T_Heal(other, amount, 0))
+ if (!T_Heal(toucher, amount, 0))
return;
}
- sprint (other, sprintf("You receive %g health\n", amount));
+ sprint (toucher, sprintf("You receive %g health\n", amount));
// health touch sound
- // sound (other, CHAN_ITEM, this.noise, 1, ATTN_NORM);
+ // sound (toucher, CHAN_ITEM, this.noise, 1, ATTN_NORM);
// custom sounds -- dumptruck_ds
- sound_misc (other, CHAN_AUTO, this.noise, 1, ATTN_NORM);
+ sound_misc (toucher, CHAN_AUTO, this.noise, 1, ATTN_NORM);
- stuffcmd (other, "bf\n");
+ stuffcmd (toucher, "bf\n");
this.model = string_null;
this.solid = SOLID_NOT;
@@ -104,9 +104,9 @@ class base_item_health: base_item
if (this.healtype == HEALTH_TYPE_MEGA)
{
// thanks ydrol!!!
- other.megahealth_rottime = time + 5;
- other.items = other.items | IT_SUPERHEALTH;
- this.owner = other;
+ toucher.megahealth_rottime = time + 5;
+ toucher.items = toucher.items | IT_SUPERHEALTH;
+ this.owner = toucher;
// Regarding the deathmatch respawn time below:
// id's original code made the megahealth respawn
@@ -134,7 +134,7 @@ class base_item_health: base_item
}
// fire all targets / killtargets
- activator = other;
+ activator = toucher;
sub_usetargets ();
};
Return to the top of this page or return to the overview of this repo.
Diff qc/items/keys.qc
diff --git a/qc/items/keys.qc b/qc/items/keys.qc
index 04285cc..bd87d3b 100644
--- a/qc/items/keys.qc
+++ b/qc/items/keys.qc
@@ -445,7 +445,8 @@ class item_key_custom: base_item_key
// this should not be referenced again
this.keyname = "";
- this.items = 0; // ignore any mapper-set value
+ // ignore any mapper-set value
+ this.items = 0;
this.customkeys = custom_key_flag (this.netname);
// key_start
Return to the top of this page or return to the overview of this repo.
Diff qc/items/powerups.qc
diff --git a/qc/items/powerups.qc b/qc/items/powerups.qc
index 55250ee..6e5cb4d 100644
--- a/qc/items/powerups.qc
+++ b/qc/items/powerups.qc
@@ -11,7 +11,7 @@ class base_item_powerup: base_item
local float delay_sp = 0;
local float delay_dm = 0;
- sprint (other, sprintf("You got the %s\n", this.netname));
+ sprint (toucher, sprintf("You got the %s\n", this.netname));
if (!deathmatch)
{
@@ -38,31 +38,31 @@ class base_item_powerup: base_item
}
}
- sound (other, CHAN_VOICE, this.noise, 1, ATTN_NORM);
- stuffcmd (other, "bf\n");
- other.items = other.items | this.items;
+ sound (toucher, CHAN_VOICE, this.noise, 1, ATTN_NORM);
+ stuffcmd (toucher, "bf\n");
+ toucher.items = toucher.items | this.items;
// do the apropriate action
if (this.classtype == CT_ITEM_ENVIROSUIT)
{
- other.rad_time = 1;
- other.radsuit_finished = time + 30;
+ toucher.rad_time = 1;
+ toucher.radsuit_finished = time + 30;
}
if (this.classtype == CT_ITEM_INVULNERABILITY)
{
- other.invincible_time = 1;
- other.invincible_finished = time + 30;
+ toucher.invincible_time = 1;
+ toucher.invincible_finished = time + 30;
}
else if (this.classtype == CT_ITEM_INVISIBILITY)
{
- other.invisible_time = 1;
- other.invisible_finished = time + 30;
+ toucher.invisible_time = 1;
+ toucher.invisible_finished = time + 30;
}
else if (this.classtype == CT_ITEM_QUAD)
{
- other.super_time = 1;
- other.super_damage_finished = time + 30;
+ toucher.super_time = 1;
+ toucher.super_damage_finished = time + 30;
}
// remove it in single player, or setup for respawning in DM
@@ -72,7 +72,7 @@ class base_item_powerup: base_item
this.model = string_null;
check_respawn (this, delay_sp, delay_dm);
- activator = other;
+ activator = toucher;
// fire all targets / killtargets
sub_usetargets ();
};
Return to the top of this page or return to the overview of this repo.
Diff qc/items/runes.qc
diff --git a/qc/items/runes.qc b/qc/items/runes.qc
index 050ebbd..1ff2f92 100644
--- a/qc/items/runes.qc
+++ b/qc/items/runes.qc
@@ -34,17 +34,17 @@ class base_item_rune: base_item
//--------------------------------------------------------------
virtual void(entity toucher) do_touch =
{
- centerprint (other, "You got the rune!");
+ centerprint (toucher, "You got the rune!");
- sound (other, CHAN_ITEM, this.noise, 1, ATTN_NORM);
- stuffcmd (other, "bf\n");
+ sound (toucher, CHAN_ITEM, this.noise, 1, ATTN_NORM);
+ stuffcmd (toucher, "bf\n");
this.solid = SOLID_NOT;
this.model = string_null;
serverflags = serverflags | (this.spawnflags & 15);
// so rune doors won't find it
this.classname = "";
- activator = other;
+ activator = toucher;
// fire all targets / killtargets
sub_usetargets ();
};
Return to the top of this page or return to the overview of this repo.
Diff qc/items/weapons.qc
diff --git a/qc/items/weapons.qc b/qc/items/weapons.qc
index 544fa84..51ed261 100644
--- a/qc/items/weapons.qc
+++ b/qc/items/weapons.qc
@@ -10,14 +10,6 @@ const float AMMO_SHELLS_WP = 5; // shells on weapon pickup; id1 5
const float WEAPON_RESPAWN_TIME = 30; // as the name suggests; id1 30
-const float AXE_ATTACK_COOLDOWN = 0.5; //
-
-// prototypes
-void() player_axe1;
-void() player_axeb1;
-void() player_axec1;
-void() player_axed1;
-
//----------------------------------------------------------------------
void() bound_other_ammo =
{
@@ -89,18 +81,15 @@ class base_item_weapon: base_item
local entity stemp;
local float leave;
- if (!(other.flags & FL_CLIENT))
+ if (!(toucher.flags & FL_CLIENT))
return;
// if the player was using his best weapon, change up to the
// new one if better
- if (other.classtype == CT_PLAYER &&
+ if (toucher.classtype == CT_PLAYER &&
autocvar(cg_autoswitch, TRUE))
{
- dprint ("base_item_weapon::do_touch: PlayerBestWeapon"
- "()\n");
- best = REMOVEME_CallAsSelfFloat (other,
- PlayerBestWeapon);
+ best = ((player)toucher).best_weapon ();
}
if (deathmatch == 2 || coop)
@@ -108,7 +97,7 @@ class base_item_weapon: base_item
leave = 1;
// fix weapon items never firing their targets in coop or
// "deathmatch 2" -- iw
- activator = other;
+ activator = toucher;
sub_useandforgettargets ();
}
else
@@ -120,66 +109,66 @@ class base_item_weapon: base_item
// -- dumptruck_ds from RRP / rubicon2
if (this.classtype == CT_ITEM_AXE)
{
- if (leave && (other.items & IT_AXE))
+ if (leave && (toucher.items & IT_AXE))
return;
new = IT_AXE;
}
else if (this.classtype == CT_ITEM_SHOTGUN)
{
- if (leave && (other.items & IT_SHOTGUN))
+ if (leave && (toucher.items & IT_SHOTGUN))
return;
- hadammo = other.ammo_shells;
+ hadammo = toucher.ammo_shells;
new = IT_SHOTGUN;
- other.ammo_shells += AMMO_SHELLS_WP;
+ toucher.ammo_shells += AMMO_SHELLS_WP;
}
else if (this.classtype == CT_ITEM_NAILGUN)
{
// johnfitz
- if (leave && (other.items & IT_NAILGUN))
+ if (leave && (toucher.items & IT_NAILGUN))
return;
- hadammo = other.ammo_nails;
+ hadammo = toucher.ammo_nails;
new = IT_NAILGUN;
- other.ammo_nails += AMMO_NAILS_WP;
+ toucher.ammo_nails += AMMO_NAILS_WP;
}
else if (this.classtype == CT_ITEM_SUPER_NAILGUN)
{
- if (leave && (other.items & IT_SUPER_NAILGUN))
+ if (leave && (toucher.items & IT_SUPER_NAILGUN))
return;
- hadammo = other.ammo_rockets;
+ hadammo = toucher.ammo_rockets;
new = IT_SUPER_NAILGUN;
- other.ammo_nails += AMMO_NAILS_WP;
+ toucher.ammo_nails += AMMO_NAILS_WP;
}
else if (this.classtype == CT_ITEM_SUPER_SHOTGUN)
{
- if (leave && (other.items & IT_SUPER_SHOTGUN))
+ if (leave && (toucher.items & IT_SUPER_SHOTGUN))
return;
- hadammo = other.ammo_rockets;
+ hadammo = toucher.ammo_rockets;
new = IT_SUPER_SHOTGUN;
- other.ammo_shells += AMMO_SHELLS_WP;
+ toucher.ammo_shells += AMMO_SHELLS_WP;
}
else if (this.classtype == CT_ITEM_ROCKET_LAUNCHER)
{
- if (leave && (other.items & IT_ROCKET_LAUNCHER))
+ if (leave && (toucher.items & IT_ROCKET_LAUNCHER))
return;
- hadammo = other.ammo_rockets;
+ hadammo = toucher.ammo_rockets;
new = IT_ROCKET_LAUNCHER;
- other.ammo_rockets += AMMO_ROCKETS_WP;
+ toucher.ammo_rockets += AMMO_ROCKETS_WP;
}
else if (this.classtype == CT_ITEM_GRENADE_LAUNCHER)
{
- if (leave && (other.items & IT_GRENADE_LAUNCHER))
+ if (leave && (toucher.items & IT_GRENADE_LAUNCHER))
return;
- hadammo = other.ammo_rockets;
+ hadammo = toucher.ammo_rockets;
new = IT_GRENADE_LAUNCHER;
- other.ammo_rockets += AMMO_ROCKETS_WP;
+ toucher.ammo_rockets += AMMO_ROCKETS_WP;
}
else if (this.classtype == CT_ITEM_LIGHTNING_GUN)
{
- if (leave && (other.items & IT_LIGHTNING))
+ if (leave && (toucher.items & IT_LIGHTNING))
return;
- hadammo = other.ammo_rockets;
+ hadammo = toucher.ammo_rockets;
new = IT_LIGHTNING;
- other.ammo_cells += AMMO_CELLS_WP;
+ toucher.ammo_cells += AMMO_CELLS_WP;
}
else
{
@@ -188,18 +177,18 @@ class base_item_weapon: base_item
return;
}
- sprint (other, sprintf("You got the %s\n", this.netname));
+ sprint (toucher, sprintf("You got the %s\n", this.netname));
// weapon touch sound
- sound (other, CHAN_ITEM, "weapons/pkup.wav", 1, ATTN_NORM);
- stuffcmd (other, "bf\n");
+ sound (toucher, CHAN_ITEM, "weapons/pkup.wav", 1, ATTN_NORM);
+ stuffcmd (toucher, "bf\n");
bound_other_ammo ();
// change to the weapon
- old = other.items;
- other.items = other.items | new;
+ old = toucher.items;
+ toucher.items = toucher.items | new;
- if (other.classtype == CT_PLAYER &&
+ if (toucher.classtype == CT_PLAYER &&
autocvar(cg_autoswitch, TRUE))
{
// 1997-12-23 Thunderbolt fix by Maddes start
@@ -211,8 +200,8 @@ class base_item_weapon: base_item
else
*/
// 1997-12-23 Thunderbolt fix by Maddes end
- REMOVEME_CallAsSelf_DeathmatchWeapon (other, old, new);
- REMOVEME_CallAsSelf (other, PlayerSetCurrentAmmo);
+ REMOVEME_CallAsSelf_DeathmatchWeapon (toucher, old, new);
+ ((player)toucher).set_current_ammo ();
}
if (leave)
@@ -225,7 +214,7 @@ class base_item_weapon: base_item
// Supa, SP respawning items support
check_respawn (this, WEAPON_RESPAWN_TIME, WEAPON_RESPAWN_TIME);
- activator = other;
+ activator = toucher;
// fire all targets / killtargets
sub_usetargets ();
};
@@ -241,56 +230,6 @@ class base_item_weapon: base_item
// Weapon 1: Ranger's Axe -- johnfitz -- dumptruck_ds from RRP and rubicon2
//=======================================================================
-//----------------------------------------------------------------------
-// W_FireAxe
-//----------------------------------------------------------------------
-void() W_FireAxe =
-{
- local vector source;
- local vector org;
-
- makevectors (self.v_angle);
- source = self.origin + '0 0 16';
- traceline (source, source + v_forward * 64, FALSE, self);
- if (trace_fraction == 1.0)
- return;
- org = trace_endpos - v_forward * 4;
-
- if (trace_ent.takedamage)
- {
- trace_ent.axhitme = 1;
- SpawnBlood (org, '0 0 0', 20);
- T_Damage (trace_ent, self, self, 20);
- }
- else
- { // hit wall
- 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() weapon_axe_attack =
-{
- local float r = random ();
- sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
-
- 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 + AXE_ATTACK_COOLDOWN;
-};
-
/*QUAKED weapon_axe (0 .5 .8) (-16 -16 0) (16 16 32)
Axe
*/
@@ -528,7 +467,52 @@ Thunderbolt
class weapon_lightning: base_item_weapon
{
//--------------------------------------------------------------
+ // this is here 'cause LG doesn't create a projectile... -- CEV
+ //--------------------------------------------------------------
+ static void(vector p1, vector p2, base_entity from, float damage)
+ lightning_damage =
+ {
+ local entity e1, e2;
+ local vector f;
+
+ f = p2 - p1;
+ normalize (f);
+ f_x = 0 - f_y;
+ f_y = f_x;
+ f_z = 0;
+ f = f * 16;
+
+ e1 = e2 = world;
+
+ traceline (p1, p2, FALSE, from);
+ if (trace_ent.takedamage)
+ {
+ particle (trace_endpos, '0 0 100', 225, damage * 4);
+ from.t_damage2 (trace_ent, from, from, damage);
+ if (from.classtype == CT_PLAYER)
+ {
+ if (other.classtype == CT_PLAYER)
+ // fly me to the moon
+ trace_ent.velocity_z += 400;
+ }
+ }
+ e1 = trace_ent;
+ traceline (p1 + f, p2 + f, FALSE, from);
+ if (trace_ent != e1 && trace_ent.takedamage)
+ {
+ particle (trace_endpos, '0 0 100', 225, damage * 4);
+ from.t_damage2 (trace_ent, from, from, damage);
+ }
+ e2 = trace_ent;
+
+ traceline (p1 - f, p2 - f, FALSE, from);
+ if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
+ {
+ particle (trace_endpos, '0 0 100', 225, damage * 4);
+ from.t_damage2 (trace_ent, from, from, damage);
+ }
+ };
//--------------------------------------------------------------
virtual void() init_spawned =
Return to the top of this page or return to the overview of this repo.
Diff qc/math.qc
diff --git a/qc/math.qc b/qc/math.qc
index 4404b8c..004d720 100644
--- a/qc/math.qc
+++ b/qc/math.qc
@@ -221,7 +221,7 @@ float(float v) anglemod =
// uses QuakeC builtins to calculate tan of angle
// WARNING: uses makevectors! This overwrites the v_forward... globals
-float(float theta) newtan =
+float(float theta) preach_tan =
{
local vector ang = '0 0 0'; // temp used to calculate trig values
@@ -231,7 +231,20 @@ float(float theta) newtan =
return v_forward_y / v_forward_x;
};
-float(float theta, vector source, vector dest) IterateElevation =
+// inverse tan function
+// takes two parameters, numerator and denominator
+// this copes better with denominator 0 and gets quadrant correct
+float(float y, float x) preach_atan2 =
+{
+ // temporary used to calculate trig values
+ local vector ang;
+ ang = '0 0 0';
+ ang_x = x;
+ ang_y = y;
+ return vectoyaw (ang);
+};
+
+float(float theta, vector source, vector dest) preach_iterate_elevation =
{
// constants in the equation to be solved
local float a, b, c;
@@ -241,7 +254,6 @@ float(float theta, vector source, vector dest) IterateElevation =
local float y, z;
// trig values of the angle theta
local float tan_theta;
- local float tan_test;
// calculate how far we are firing
ofs = dest - source;
@@ -250,7 +262,7 @@ float(float theta, vector source, vector dest) IterateElevation =
y = vlen (ofs);
// find the coefficients of the quadratic in tan(theta)
- a = 0.5 * pgrav * y * y / (OGRE_G_VEL * OGRE_G_VEL);
+ a = 0.5 * frame_gravity * y * y / (GRENADE_SPEED * GRENADE_SPEED);
b = -y;
c = a + z;
@@ -259,15 +271,11 @@ float(float theta, vector source, vector dest) IterateElevation =
return OGRE_DEFAULT_ELEVATION;
// calculate the tan value of the given theta
- tan_theta = newtan (theta);
- tan_test = tan (theta);
-
- // TODO CEV
- dprint (sprintf("IterateElevation: tan: %f, newtan: %f\n",
- tan_test, tan_theta));
+ tan_theta = preach_tan (theta);
// reuse ang to create the improved firing direction
- theta = atan2 (a * tan_theta * tan_theta - c, 2 * a * tan_theta + b);
+ theta = preach_atan2 (a * tan_theta * tan_theta - c,
+ 2 * a * tan_theta + b);
// constrain the values to stop anything too mad happening
while (theta > 90)
Return to the top of this page or return to the overview of this repo.
Diff qc/misc/explobox.qc
diff --git a/qc/misc/explobox.qc b/qc/misc/explobox.qc
index 9d27622..9666cb6 100644
--- a/qc/misc/explobox.qc
+++ b/qc/misc/explobox.qc
@@ -5,12 +5,13 @@
//----------------------------------------------------------------------
class base_explobox: base_mapentity
{
- nonvirtual void() barrel_explode =
+ //--------------------------------------------------------------
+ virtual void() do_destroy =
{
this.takedamage = DAMAGE_NO;
this.classname = "explo_box";
// did say this.owner
- T_RadiusDamage (this, this, 160, world);
+ this.t_radiusdamage2 (this, this, 160, world);
sound (this, CHAN_VOICE, "weapons/r_exp3.wav", 1, ATTN_NORM);
particle (this.origin, '0 0 0', 75, 255);
@@ -38,11 +39,12 @@ class misc_explobox: base_explobox
setmodel (this, "maps/b_explob.bsp");
precache_sound ("weapons/r_exp3.wav");
this.health = 20;
- this.th_die = barrel_explode;
+ this.th_die = this.do_destroy;
this.takedamage = DAMAGE_AIM;
// 1998-09-16 Sliding/not-jumping on monsters/boxes/players
// fix by Maddes/Kryten
- this.touch = monster_touch;
+ // TODO CEV
+ // this.touch = monster_touch;
this.origin_z = this.origin_z + 2;
local float oldz = this.origin_z;
@@ -80,11 +82,12 @@ class misc_explobox2: base_explobox
setmodel (this, "maps/b_exbox2.bsp");
precache_sound ("weapons/r_exp3.wav");
this.health = 20;
- this.th_die = barrel_explode;
+ this.th_die = this.do_destroy;
this.takedamage = DAMAGE_AIM;
// 1998-09-16 Sliding/not-jumping on monsters/boxes/players
// fix by Maddes/Kryten
- this.touch = monster_touch;
+ // TODO CEV
+ // this.touch = monster_touch;
this.origin_z = this.origin_z + 2;
local float oldz = this.origin_z;
Return to the top of this page or return to the overview of this repo.
Diff qc/misc/fireball.qc
diff --git a/qc/misc/fireball.qc b/qc/misc/fireball.qc
index 8b6a202..d12c9ed 100644
--- a/qc/misc/fireball.qc
+++ b/qc/misc/fireball.qc
@@ -14,7 +14,7 @@ class temp_fireball: base_tempentity
//--------------------------------------------------------------
virtual void(entity toucher) do_touch =
{
- T_Damage (toucher, this, this, 20);
+ t_damage2 (toucher, this, this, 20);
remove (this);
};
Return to the top of this page or return to the overview of this repo.
Diff qc/misc/infight.qc
diff --git a/qc/misc/infight.qc b/qc/misc/infight.qc
index bfc2117..0348fc5 100644
--- a/qc/misc/infight.qc
+++ b/qc/misc/infight.qc
@@ -29,9 +29,7 @@ class misc_infight: base_mapentity
t1.oldenemy = t1.enemy;
t1.enemy = t2;
- // TODO CEV need to rework; this/self/FoundTarget
- // FoundTarget () only acts on self
- // FoundTargetForEntity (t1);
+ // was FoundTargetForEntity (t1) -- CEV
if (t1.classgroup & CG_MONSTER)
{
((base_monster)t1).ai_findtarget ();
Return to the top of this page or return to the overview of this repo.
Diff qc/misc/play.qc
diff --git a/qc/misc/play.qc b/qc/misc/play.qc
index ad74851..6fd9ca1 100644
--- a/qc/misc/play.qc
+++ b/qc/misc/play.qc
@@ -224,9 +224,10 @@ class play_explosion: base_mapentity
virtual void(entity caller) do_use =
{
// thanks Khreathor -- dumptruck_ds
- // GrenadeExplode uses this.owner as the attacker -- iw
- this.owner = this;
- GrenadeExplode ();
+ t_radiusdamage2 (this, this, 120, world);
+ base_explosion::write_explosion (this.origin);
+ spawn (base_explosion, origin: this.origin);
+ remove (this);
};
//--------------------------------------------------------------
Return to the top of this page or return to the overview of this repo.
Diff qc/monsters.qc
diff --git a/qc/monsters.qc b/qc/monsters.qc
deleted file mode 100644
index 8d9af8e..0000000
--- a/qc/monsters.qc
+++ /dev/null
@@ -1,553 +0,0 @@
-/* ALL MONSTERS SHOULD BE 1 0 0 IN COLOR */
-
-// name =[framenum, nexttime, nextthink] {code}
-// expands to:
-// name ()
-// {
-// self.frame=framenum;
-// self.nextthink = time + nexttime;
-// self.think = nextthink
-// <code>
-// };
-
-/*
-================
-monster_update_total
-
-Call this function to safely update total_monsters when the game is in
-progress. It adds "n" to total_monsters, then notifies all clients of
-the change. -- iw
-================
-*/
-void(float n) monster_update_total =
-{
- total_monsters = total_monsters + n;
-
- WriteByte (MSG_ALL, SVC_UPDATESTAT);
- WriteByte (MSG_ALL, STAT_TOTALMONSTERS);
- WriteLong (MSG_ALL, total_monsters);
-};
-
-/* From Preach's tutorial here: https://tomeofpreach.wordpress.com/2017/10/08/teleporting-monsters-flag/#more-2281 */
-
-/*
-//define Preach's new fields dumptruck_ds
-
-.string tele_model;
-.vector tele_mins;
-.vector tele_maxs;
-.float tele_solid;
-.float tele_movetype;
-*/
-
-void() monster_teleport_go =
-{
- self.solid = self.tele_solid;
- self.movetype = self.tele_movetype;
- setmodel(self, self.tele_model);
- setsize (self, self.tele_mins, self.tele_maxs);
-
- // fix for cumulative delays for counters etc. -- dumptruck_ds
- self.delay = 0;
-
- self.think1();
- //override the random delay some go functions apply
- self.nextthink = time + 0.1;
- {
- if !(self.spawnflags & SPAWN_SILENTLY)
- {
- // dumptruck_ds: if wait value is > 0 spawn silently
- // or use a spawnflag
- if (self.wait == 0)
- spawn_tfog (self.origin);
- spawn_tdeath(self.origin, self);
- }
- }
-
-}
-
-// new from Qmaster func coding help thread
-void() monster_teleport_delay =
-{
- self.think = monster_teleport_go;
- if (self.delay == -1)
- {
- // if delay is set to -1 random delay from 0.1 to 1
- // second - dumptruck_ds
- self.nextthink = time + 0.1 + random();
- return;
- }
- self.nextthink = time + 0.1 + self.delay;
-};
-
-/*
-================
-monster_teleport_check
-
-This detects and eliminates a common map bug: a trigger-spawned monster
-which can't be activated either because it has no targetname or because
-its targetname isn't targeted by any other entity. (This map bug would
-otherwise make it impossible for the player to get 100% kills.) -- iw
-================
-*/
-void() monster_teleport_check =
-{
- if (!SUB_IsTargeted ())
- {
- dprint ("WARNING: removed untargeted trigger-spawned ");
- dprint (self.classname);
- dprint (" at ");
- dprint (vtos (self.origin));
- dprint ("\n");
-
- remove (self);
- return;
- }
-
- // the targetname appears to be OK, so let's finish setting up the
- // trigger-spawned monster -- iw
- self.use = monster_teleport_delay; // qmaster
- monster_update_total (1);
-};
-
-float (void() monster_start_fn) monster_teleport =
-{
- if(!(self.spawnflags & 8))
- return FALSE;
-
- // PREACH: This monster is to be teleported in, so hide it
- self.tele_model= self.model;
- self.tele_mins = self.mins;
- self.tele_maxs = self.maxs;
- self.tele_solid = self.solid;
- self.tele_movetype = self.movetype;
-
- self.model = "";
- self.modelindex = 0;
- self.solid = SOLID_NOT;
- self.movetype = MOVETYPE_NONE;
- self.think1 = monster_start_fn;
-
- // wait for other entities to finish spawning, then check that
- // something targets this -- iw
- self.think = monster_teleport_check;
- self.nextthink = time + 0.1;
-
- return TRUE;
-}
-
-//end of Preach's new fields here
-
-// 1998-09-16 Sliding/not-jumping on monsters/boxes/players fix by Maddes/Kryten start
-/*
-================
-by: Philip Martin aka: Kryten
-When on top of monsters or players you slide. This is a QuakeC problem.
-The function below fixes that problem.
-based on code given to Kryten by: Michael Turitzin (MaNiAc)
-================
-*/
-void() monster_touch =
-{
- //can cause problems for monsters on top of a player, so only players
- if (other.classname != "player")
- return;
- if (other.health <= 0)
- return;
-
- if ((!(other.flags & FL_ONGROUND)) &&
- ((other.absmin_z >= self.absmax_z - 2)))
- {
- other.flags = other.flags + FL_ONGROUND;
- }
-
- // you can add other stuff like pushable players/monsters here
-};
-// 1998-09-16 Sliding/not-jumping on monsters/boxes/players fix by Maddes/Kryten end
-
-/*
-================
-monster_use
-
-Using a monster makes it angry at the current activator
-================
-*/
-void() monster_use =
-{
- if (self.enemy)
- return;
- if (self.health <= 0)
- return;
- if (activator.items & IT_INVISIBILITY)
- return;
- if (activator.flags & FL_NOTARGET)
- return;
- if (activator.movetype == MOVETYPE_NOCLIP)
- // Copper -- dumptruck_ds
- return FALSE;
-
- if (activator.classname != "player")
- return;
-
-
- // delay reaction so if the monster is teleported, its sound is still
- // heard
- self.enemy = activator;
- self.nextthink = time + 0.1;
- self.think = FoundTarget;
-};
-
-/*
-================
-monster_death_use
-
-When a mosnter dies, it fires all of its targets with the current
-enemy as activator.
-================
-*/
-void() monster_death_use =
-{
- // fall to ground
- if (self.flags & FL_FLY)
- self.flags = self.flags - FL_FLY;
- if (self.flags & FL_SWIM)
- self.flags = self.flags - FL_SWIM;
-
- if (!self.target)
- return;
-
- if(self.infight_activator)
- {
- activator = self.infight_activator;
- }
- else
- {
- activator = self.enemy;
- }
- SUB_UseTargets ();
-};
-
-/*
-================
-monster_pain_use //dumptruck_ds
-
-When a monster reaches pain_threshold, it fires all of its pain_targets
-with the current enemy as activator.
-================
-*/
-void() monster_pain_use =
-{
- if (!self.pain_target)
- return;
-
- activator = self.enemy;
- SUB_UsePain ();
-};
-
-//============================================================================
-
-void() walkmonster_start_go =
-{
- // raise off floor a bit
- self.origin_z = self.origin_z + 1;
-
- // Preach's "check" here
-
- // if(time <= 0.5)
- if(!(self.spawnflags & 8))
- {
- droptofloor();
-
- if !(self.spawnflags & I_AM_TURRET)
- {
- // fixes an incorrect dprint -- dumptruck_ds
- if (!walkmove(0,0))
- {
- dprint ("\n\n");
- dprint (self.classname);
- dprint (" in wall at: ");
- dprint (vtos(self.origin));
- dprint ("\n\n");
- }
- }
- }
-
- self.takedamage = DAMAGE_AIM;
-
- self.ideal_yaw = self.angles * '0 1 0';
- if (!self.yaw_speed)
- self.yaw_speed = 20;
- self.view_ofs = '0 0 25';
- self.use = monster_use;
-
- self.flags = self.flags | FL_MONSTER;
-
- if (self.target != "")
- {
- self.goalentity = self.movetarget = find (world,
- targetname, self.target);
- self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
- if (!self.movetarget)
- {
- dprint ("Monster can't find target at ");
- dprint (vtos(self.origin));
- dprint ("\n");
- }
-
- // this used to be an objerror
- if (self.movetarget.classname == "path_corner")
- {
- self.th_walk ();
- }
- else
- {
- self.pausetime = 99999999;
- self.th_stand ();
- }
- }
- else
- {
- self.pausetime = 99999999;
- self.th_stand ();
- }
-
- // spread think times so they don't all happen at same time
- // 1998-08-14 Monsters sometimes do not move fix by Lord Sméagol start
- // self.nextthink = self.nextthink + random()*0.5;
- self.nextthink = time + 0.1 + random()*0.5;
- // 1998-08-14 Monsters sometimes do not move fix by Lord Sméagol end
- // dumptruck_ds -- using spawn_angry set to 1 in order to spawn
- // in "angry" monsters
- // if ((self.spawnflags & 8) && self.spawn_angry == 1)
- // {
- // monster_use();
- // }
-
- // dumptruck_ds -- this is Shamblernaut's method
- local entity pl;
-
- pl = find (world, classname, "player");
-
- if (self.spawn_angry == 1)
- {
- activator = pl;
- monster_use();
- }
-};
-
-// Preach's tutorial
-void() walkmonster_start =
-{
- if (cvar("nomonsters"))
- {
- remove (self);
- return;
- }
-
- if (monster_teleport(walkmonster_start_go))
- return;
-
- // delay drop to floor to make sure all doors have been spawned
- // spread think times so they don't all happen at same time
-
- // 1998-09-16 Sliding/not-jumping on monsters/boxes/players fix
- // by Maddes/Kryten
- self.touch = monster_touch;
- // 1998-08-14 Monsters sometimes do not move fix by Lord Sméagol start
- // self.nextthink = self.nextthink + random()*0.5;
- self.nextthink = time + 0.1 + random()*0.5;
- // 1998-08-14 Monsters sometimes do not move fix by Lord Sméagol end
- self.think = walkmonster_start_go;
- total_monsters = total_monsters + 1;
- /// Trigger enemy after spawn (khreathor)
-};
-
-void() flymonster_start_go =
-{
- self.takedamage = DAMAGE_AIM;
-
- self.ideal_yaw = self.angles * '0 1 0';
- if (!self.yaw_speed)
- self.yaw_speed = 10;
- self.view_ofs = '0 0 25';
- self.use = monster_use;
-
- self.flags = self.flags | FL_FLY;
- self.flags = self.flags | FL_MONSTER;
-
- if (!walkmove(0,0))
- {
- dprint ("flymonster in wall at: ");
- dprint (vtos(self.origin));
- dprint ("\n");
- }
-
- if (self.target != "")
- {
- self.goalentity = self.movetarget = find (world,
- targetname, self.target);
- if (!self.movetarget)
- {
- dprint ("Monster can't find target at ");
- dprint (vtos(self.origin));
- dprint ("\n");
- }
-
- // this used to be an objerror
- if (self.movetarget.classname == "path_corner")
- {
- self.th_walk ();
- }
- else
- {
- self.pausetime = 99999999;
- self.th_stand ();
- }
- }
- else
- {
- self.pausetime = 99999999;
- self.th_stand ();
- }
-
- // 1998-08-14 Monsters sometimes do not move fix by Lord Sméagol
- self.nextthink = time + 0.1 + random()*0.5;
-
- // dumptruck_ds -- using spawn_angry set to 1 in order to spawn
- // in "angry" monsters
- // if ((self.spawnflags & 8) && self.spawn_angry == 1)
- // {
- // monster_use();
- // }
-
- //dumptruck_ds -- this is Shamblernaut's method
- local entity pl;
-
- pl = find (world, classname, "player");
-
- if (self.spawn_angry == 1)
- {
- activator = pl;
- monster_use();
- }
-};
-
-void() flymonster_start =
-{
- if (cvar("nomonsters"))
- {
- remove (self);
- return;
- }
-
- // Preach's tutorial
-
- if (monster_teleport(flymonster_start_go))
- return;
-
- // 1998-09-16 Sliding/not-jumping on monsters/boxes/players
- // fix by Maddes/Kryten
- self.touch = monster_touch;
- // 1998-08-14 Monsters sometimes do not move fix by Lord Sméagol
- self.flags = self.flags | FL_FLY;
-
- // spread think times so they don't all happen at same time
- // 1998-08-14 Monsters sometimes do not move fix by Lord Sméagol start
- // self.nextthink = self.nextthink + random()*0.5;
- self.nextthink = time + 0.1 + random()*0.5;
- // 1998-08-14 Monsters sometimes do not move fix by Lord Sméagol end
- self.think = flymonster_start_go;
- total_monsters = total_monsters + 1;
-};
-
-void() swimmonster_start_go =
-{
- if (deathmatch)
- {
- remove (self);
- return;
- }
-
- self.takedamage = DAMAGE_AIM;
-
- self.ideal_yaw = self.angles * '0 1 0';
- if (!self.yaw_speed)
- self.yaw_speed = 10;
- self.view_ofs = '0 0 10';
- self.use = monster_use;
-
- self.flags = self.flags | FL_SWIM;
- self.flags = self.flags | FL_MONSTER;
-
- if (self.target != "")
- {
- self.goalentity = self.movetarget = find (world,
- targetname, self.target);
- if (!self.movetarget)
- {
- dprint ("Monster can't find target at ");
- dprint (vtos(self.origin));
- dprint ("\n");
- }
- // this used to be an objerror
- self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
- self.th_walk ();
- }
- else
- {
- self.pausetime = 99999999;
- self.th_stand ();
- }
-
- // spread think times so they don't all happen at same time
- // 1998-08-14 Monsters sometimes do not move fix by Lord Sméagol start
- // self.nextthink = self.nextthink + random()*0.5;
- self.nextthink = time + 0.1 + random()*0.5;
- // 1998-08-14 Monsters sometimes do not move fix by Lord Sméagol end
-
- // dumptruck_ds -- using spawn_angry set to 1 in order to spawn
- // in "angry" monsters
- // if ((self.spawnflags & 8) && self.spawn_angry == 1)
- // {
- // monster_use();
- // }
-
- // dumptruck_ds -- this is Shamblernaut's method
- local entity pl;
-
- pl = find (world, classname, "player");
-
- if (self.spawn_angry == 1)
- {
- activator = pl;
- monster_use();
- }
-};
-
-void() swimmonster_start =
-{
- if (cvar("nomonsters"))
- {
- remove (self);
- return;
- }
-
- // 1998-09-16 Sliding/not-jumping on monsters/boxes/players
- // fix by Maddes/Kryten
- self.touch = monster_touch;
- // 1998-08-14 Monsters sometimes do not move fix by Lord Sméagol
- self.flags = self.flags | FL_SWIM;
-
- // Preach's tutorial
-
- if (monster_teleport(swimmonster_start_go))
- return;
-
- // spread think times so they don't all happen at same time
- // 1998-08-14 Monsters sometimes do not move fix by Lord Sméagol start
- // self.nextthink = self.nextthink + random()*0.5;
- self.nextthink = time + 0.1 + random()*0.5;
- // 1998-08-14 Monsters sometimes do not move fix by Lord Sméagol end
- self.think = swimmonster_start_go;
- total_monsters = total_monsters + 1;
-};
Return to the top of this page or return to the overview of this repo.
Diff qc/monsters/boss.qc
diff --git a/qc/monsters/boss.qc b/qc/monsters/boss.qc
index 07c9b94..782862d 100644
--- a/qc/monsters/boss.qc
+++ b/qc/monsters/boss.qc
@@ -59,55 +59,29 @@ class monster_boss: base_monster
//--------------------------------------------------------------
nonvirtual void(vector p) attack_missile =
{
- local vector offang;
- local vector org, vec, d;
+ local vector org, d;
local float t;
- offang = vectoangles (this.enemy.origin - this.origin);
- makevectors (offang);
+ makevectors (vectoangles(this.enemy.origin - this.origin));
- org = this.origin + p_x*v_forward + p_y*v_right + p_z*'0 0 1';
+ org = this.origin + p_x * v_forward + p_y * v_right +
+ p_z * '0 0 1';
// lead the player on hard mode
if (skill > 1)
{
t = vlen(this.enemy.origin - org) / 300;
- vec = this.enemy.velocity;
- vec_z = 0;
- d = this.enemy.origin + t * vec;
+ d = this.enemy.velocity;
+ d_z = 0;
+ d = this.enemy.origin + t * d;
}
else
{
d = this.enemy.origin;
}
- vec = normalize (d - org);
+ fire_lavaball (org, d - org, LAVABALL_SPEED);
- launch_spike2 (org, vec, 300);
- // setmodel (newmis, "progs/lavaball.mdl");
- if (this.mdl_proj != "") // dumptruck_ds custom_mdls
- {
- setmodel (newmis, this.mdl_proj);
- }
- else
- {
- setmodel (newmis, "progs/lavaball.mdl");
- }
-
- // dumptruck_ds
- if (!newmis.skin_proj)
- {
- newmis.skin = this.skin_proj;
- }
- else
- {
- newmis.skin = 0;
- }
-
- newmis.avelocity = '200 100 300';
- setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
- // rocket explosion
- newmis.touch = T_MissileTouch;
sound_attack (this, CHAN_WEAPON, "boss1/throw.wav",
1, ATTN_NORM);
Return to the top of this page or return to the overview of this repo.
Diff qc/monsters/boss2.qc
diff --git a/qc/monsters/boss2.qc b/qc/monsters/boss2.qc
index 0a315ed..da8300d 100644
--- a/qc/monsters/boss2.qc
+++ b/qc/monsters/boss2.qc
@@ -65,12 +65,10 @@ class monster_boss2: base_monster
//--------------------------------------------------------------
nonvirtual void(vector p) attack_missile =
{
- local vector offang;
- local vector org, vec, d;
+ local vector org, d;
local float t;
- offang = vectoangles (this.enemy.origin - this.origin);
- makevectors (offang);
+ makevectors (vectoangles(this.enemy.origin - this.origin));
org = this.origin + p_x * v_forward + p_y * v_right +
p_z * '0 0 1';
@@ -78,44 +76,18 @@ class monster_boss2: base_monster
// lead the player on hard mode
if (skill > 1)
{
- t = vlen (this.enemy.origin - org) / 300;
- vec = this.enemy.velocity;
- vec_z = 0;
- d = this.enemy.origin + t * vec;
+ t = vlen(this.enemy.origin - org) / 300;
+ d = this.enemy.velocity;
+ d_z = 0;
+ d = this.enemy.origin + t * d;
}
else
{
d = this.enemy.origin;
}
- vec = normalize (d - org);
+ fire_lavaball (org, d - org, LAVABALL_SPEED);
- launch_spike2 (org, vec, 300);
- // setmodel (newmis, "progs/lavaball.mdl");
- // dumptruck_ds custom_mdls
- if (this.mdl_proj != "")
- {
- setmodel (newmis, this.mdl_proj);
- }
- else
- {
- setmodel (newmis, "progs/lavaball.mdl");
- }
-
- // dumptruck_ds
- if (!newmis.skin_proj)
- {
- newmis.skin = this.skin_proj;
- }
- else
- {
- newmis.skin = 0;
- }
-
- newmis.avelocity = '200 100 300';
- setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
- // rocket explosion
- newmis.touch = T_MissileTouch;
sound_attack (this, CHAN_WEAPON, "boss1/throw.wav",
1, ATTN_NORM);
Return to the top of this page or return to the overview of this repo.
Diff qc/monsters/demon.qc
diff --git a/qc/monsters/demon.qc b/qc/monsters/demon.qc
index c468300..bfeb343 100644
--- a/qc/monsters/demon.qc
+++ b/qc/monsters/demon.qc
@@ -204,7 +204,7 @@ class monster_demon1: base_walkmonster
};
//--------------------------------------------------------------
- nonvirtual void() do_destroy =
+ virtual void() do_destroy =
{
// check for gib
if (this.health < -80)
@@ -271,12 +271,12 @@ class monster_demon1: base_walkmonster
if (vlen(delta) > 100)
return;
- if (!CanDamage (this.enemy, this))
+ if (!this.can_damage(this, this.enemy))
return;
sound_hit (this, CHAN_WEAPON, "demon/dhit2.wav", 1, ATTN_NORM);
ldmg = 10 + 5 * random ();
- T_Damage (this.enemy, this, this, ldmg);
+ this.t_damage2 (this.enemy, this, this, ldmg);
makevectors (this.angles);
SpawnMeatSpray (this.origin + v_forward * 16, side * v_right);
@@ -446,7 +446,7 @@ class monster_demon1: base_walkmonster
if !(this.worldtype)
{
ldmg = 40 + 10 * random();
- T_Damage (other, this, this, ldmg);
+ this.t_damage2 (other, this, this, ldmg);
// is the player still alive?
// Preach's instakill bug check
// - dumptruck_ds
Return to the top of this page or return to the overview of this repo.
Diff qc/monsters/dog.qc
diff --git a/qc/monsters/dog.qc b/qc/monsters/dog.qc
index ce061e5..3020712 100644
--- a/qc/monsters/dog.qc
+++ b/qc/monsters/dog.qc
@@ -195,7 +195,7 @@ class monster_dog: base_walkmonster
ai_charge (10);
- if (!CanDamage (this.enemy, this))
+ if (!this.can_damage(this, this.enemy))
return;
delta = this.enemy.origin - this.origin;
@@ -204,7 +204,7 @@ class monster_dog: base_walkmonster
return;
ldmg = (random() + random() + random()) * 8;
- T_Damage (this.enemy, this, this, ldmg);
+ this.t_damage2 (this.enemy, this, this, ldmg);
};
//--------------------------------------------------------------
@@ -456,8 +456,8 @@ class monster_dog: base_walkmonster
{
if !(this.worldtype)
{
- ldmg = 10 + 10*random();
- T_Damage (other, this, this, ldmg);
+ ldmg = 10 + 10 * random();
+ this.t_damage2 (other, this, this, ldmg);
if (other.health > 0)
// is the player still alive?
// Preach's instakill bug check
Return to the top of this page or return to the overview of this repo.
Diff qc/monsters/enforcer.qc
diff --git a/qc/monsters/enforcer.qc b/qc/monsters/enforcer.qc
index 8b07a07..7ef3cf4 100644
--- a/qc/monsters/enforcer.qc
+++ b/qc/monsters/enforcer.qc
@@ -48,7 +48,7 @@ keep_ammo(integer) : "1 = Don't drop backpack upon death"
style(Choices) : "Attack type"
0 : "Default (lasers)"
-1 : "rockets"
+1 : "rockets"
2 : "grenades"
3 : "nails"
@@ -169,7 +169,7 @@ class monster_enforcer: base_walkmonster
WriteCoord (MSG_BROADCAST, trace_endpos_y);
WriteCoord (MSG_BROADCAST, trace_endpos_z);
- LightningDamage (org, trace_endpos, this, 4);
+ weapon_lightning::lightning_damage (org, trace_endpos, this, 4);
};
//--------------------------------------------------------------
@@ -182,46 +182,55 @@ class monster_enforcer: base_walkmonster
ai_face ();
sound_attack (this, CHAN_WEAPON, "enforcer/enfire.wav",
1, ATTN_NORM);
- EnfRocket ();
+
+ makevectors (this.angles);
+ // last number was 16 - dumptruck_ds
+ local vector org = this.origin + v_forward * 30 +
+ v_right * 8.5 + '0 0 12';
+
+ // org, dir, direct_damage, splash_damage, speed
+ fire_rocket (org, this.enemy.origin - this.origin,
+ 30, 40, 900);
return;
}
else if (this.style == 2)
{
- this.effects = this.effects | EF_MUZZLEFLASH;
ai_face ();
+ // TODO CEV calling makevectors here & then again in
+ // fire_grenade below is not ideal
+ makevectors (this.angles);
+ // enforcer grenade offset -- CEV
+ local vector org1 = this.origin +
+ (v_forward * 30 + v_right * 8.5 + '0 0 16');
if (this.spawnflags & I_AM_TURRET)
- // TODO CEV
- // PreachFireGrenade (this.attack_elevation);
- dprint ("monster_enforcer::atk_laser: need to "
- "implement PreachFireGrenade ()\n");
+ fire_grenade (org1, 40, 40, attack_elevation);
else
- EnfFireGrenade ();
+ fire_grenade (org1, 40, 40, 0);
return;
}
- else if (this.style == 3 || this.style ==5)
+ else if (this.style == 3 || this.style == 5)
{
- local vector foo;
-
+ sound_attack (this, CHAN_WEAPON, "weapons/spike2.wav",
+ 1, ATTN_NORM);
this.effects = this.effects | EF_MUZZLEFLASH;
makevectors (this.angles);
- foo = this.origin + v_forward * 30 +
- v_right * 8.5 + '0 0 16';
-
- EnfLaunchSpike (foo, this.enemy.origin - this.origin);
+ // this is changed from pd3, speed there was 600; I've
+ // set it to standard SPIKE_SPEED (1000) here -- CEV
+ fire_spike (this.origin +
+ (v_forward * 30 + v_right * 8.5 + '0 0 16'),
+ this.enemy.origin - this.origin,
+ SPIKE_SUPER_DAMAGE, SPIKE_SPEED);
return;
}
else
{
- local vector org;
-
- this.effects = this.effects | EF_MUZZLEFLASH;
makevectors (this.angles);
- org = this.origin + v_forward * 30 +
- v_right * 8.5 + '0 0 16';
+ local vector org2 = this.origin +
+ (v_forward * 30 + v_right * 8.5 + '0 0 16');
- LaunchLaser (org, this.enemy.origin - this.origin);
+ fire_laser (org2, this.enemy.origin - this.origin);
}
};
@@ -369,59 +378,59 @@ class monster_enforcer: base_walkmonster
//--------------------------------------------------------------
// Enforcer turret attack 1
//--------------------------------------------------------------
- nonvirtual void() turret_atk1 = [$attack1, turret_atk2] { ai_face (); };
- nonvirtual void() turret_atk2 = [$attack2, turret_atk3] { ai_face (); };
- nonvirtual void() turret_atk3 = [$attack3, turret_atk4]
+ nonvirtual void() tur_atk1 = [$attack1, tur_atk2] { ai_face (); };
+ nonvirtual void() tur_atk2 = [$attack2, tur_atk3] { ai_face (); };
+ nonvirtual void() tur_atk3 = [$attack3, tur_atk4]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
OGRE_DEFAULT_ELEVATION, this.origin, this.enemy.origin);
};
- nonvirtual void() turret_atk4 = [$attack4, turret_atk5]
+ nonvirtual void() tur_atk4 = [$attack4, tur_atk5]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
this.attack_elevation, this.origin, this.enemy.origin);
};
- nonvirtual void() turret_atk5 = [$attack5, turret_atk6]
+ nonvirtual void() tur_atk5 = [$attack5, tur_atk6]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
this.attack_elevation, this.origin, this.enemy.origin);
};
- nonvirtual void() turret_atk6 = [$attack6, turret_atk7]
+ nonvirtual void() tur_atk6 = [$attack6, tur_atk7]
{
atk_laser ();
};
- nonvirtual void() turret_atk7 = [$attack7, turret_atk8]
+ nonvirtual void() tur_atk7 = [$attack7, tur_atk8]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
OGRE_DEFAULT_ELEVATION, this.origin, this.enemy.origin);
};
- nonvirtual void() turret_atk8 = [$attack8, turret_atk9]
+ nonvirtual void() tur_atk8 = [$attack8, tur_atk9]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
this.attack_elevation, this.origin, this.enemy.origin);
};
- nonvirtual void() turret_atk9 = [$attack5, turret_atk10]
+ nonvirtual void() tur_atk9 = [$attack5, tur_atk10]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
this.attack_elevation, this.origin, this.enemy.origin);
};
- nonvirtual void() turret_atk10 = [$attack6, turret_atk11]
+ nonvirtual void() tur_atk10 = [$attack6, tur_atk11]
{
atk_laser ();
};
- nonvirtual void() turret_atk11 = [$attack7, turret_atk12] { ai_face ();};
- nonvirtual void() turret_atk12 = [$attack8, turret_atk13] { ai_face ();};
- nonvirtual void() turret_atk13 = [$attack9, turret_atk14] { ai_face ();};
- nonvirtual void() turret_atk14 = [$attack10, seek_stand1]
+ nonvirtual void() tur_atk11 = [$attack7, tur_atk12] { ai_face (); };
+ nonvirtual void() tur_atk12 = [$attack8, tur_atk13] { ai_face (); };
+ nonvirtual void() tur_atk13 = [$attack9, tur_atk14] { ai_face (); };
+ nonvirtual void() tur_atk14 = [$attack10, seek_stand1]
{
ai_face ();
- sub_checkrefire (turret_atk1);
+ sub_checkrefire (tur_atk1);
};
//--------------------------------------------------------------
@@ -438,17 +447,17 @@ class monster_enforcer: base_walkmonster
//--------------------------------------------------------------
// Enforcer turret attack 2 (?)
//--------------------------------------------------------------
- nonvirtual void() enf2turret_atk1 = [$attack1, enf2turret_atk2]
+ nonvirtual void() enf2tur_atk1 = [$attack1, enf2tur_atk2]
{
ai_face ();
this.count = 0;
this.t_length = 4 + floor (random() * 4);
};
- nonvirtual void() enf2turret_atk2 = [$attack2, enf2turret_atk3] {ai_face ();};
- nonvirtual void() enf2turret_atk3 = [$attack3, enf2turret_atk4] {ai_face ();};
- nonvirtual void() enf2turret_atk4 = [$attack4, enf2turret_atk5] {ai_face ();};
- nonvirtual void() enf2turret_atk5 = [$attack5, enf2turret_atk6] {ai_face ();};
- nonvirtual void() enf2turret_atk6 =
+ nonvirtual void() enf2tur_atk2 = [$attack2, enf2tur_atk3] {ai_face ();};
+ nonvirtual void() enf2tur_atk3 = [$attack3, enf2tur_atk4] {ai_face ();};
+ nonvirtual void() enf2tur_atk4 = [$attack4, enf2tur_atk5] {ai_face ();};
+ nonvirtual void() enf2tur_atk5 = [$attack5, enf2tur_atk6] {ai_face ();};
+ nonvirtual void() enf2tur_atk6 =
{
this.frame = $attack6;
this.nextthink = time + 0.1;
@@ -458,47 +467,47 @@ class monster_enforcer: base_walkmonster
}
else
{
- this.think = this.enf2turret_atk7;
+ this.think = this.enf2tur_atk7;
}
ai_face ();
atk_laser ();
};
- nonvirtual void() enf2turret_atk7 = [$attack7, enf2turret_atk8] {ai_face ();};
- nonvirtual void() enf2turret_atk8 = [$attack8, enf2turret_atk9] {ai_face ();};
- nonvirtual void() enf2turret_atk9 = [$attack9, enf2turret_atk10] {ai_face();};
- nonvirtual void() enf2turret_atk10 = [$attack10, enf2stand1]
+ nonvirtual void() enf2tur_atk7 = [$attack7, enf2tur_atk8] {ai_face ();};
+ nonvirtual void() enf2tur_atk8 = [$attack8, enf2tur_atk9] {ai_face ();};
+ nonvirtual void() enf2tur_atk9 = [$attack9, enf2tur_atk10] {ai_face();};
+ nonvirtual void() enf2tur_atk10 = [$attack10, enf2stand1]
{
ai_face ();
- sub_checkrefire (enf2turret_atk1);
+ sub_checkrefire (enf2tur_atk1);
};
//--------------------------------------------------------------
// Enforcer turret attack 4 (?)
//--------------------------------------------------------------
- nonvirtual void() enf4turret_atk1 = [$attack1, enf4turret_atk2] {ai_face ();};
- nonvirtual void() enf4turret_atk2 = [$attack2, enf4turret_atk3] {ai_face ();};
- nonvirtual void() enf4turret_atk3 = [$attack3, enf4turret_atk4] {ai_face ();};
- nonvirtual void() enf4turret_atk4 = [$attack4, enf4turret_atk5] {ai_face ();};
- nonvirtual void() enf4turret_atk5 = [$attack5, enf4turret_atk6] {ai_face ();};
- nonvirtual void() enf4turret_atk6 = [$attack6, enf4turret_atk7]
+ nonvirtual void() enf4tur_atk1 = [$attack1, enf4tur_atk2] {ai_face ();};
+ nonvirtual void() enf4tur_atk2 = [$attack2, enf4tur_atk3] {ai_face ();};
+ nonvirtual void() enf4tur_atk3 = [$attack3, enf4tur_atk4] {ai_face ();};
+ nonvirtual void() enf4tur_atk4 = [$attack4, enf4tur_atk5] {ai_face ();};
+ nonvirtual void() enf4tur_atk5 = [$attack5, enf4tur_atk6] {ai_face ();};
+ nonvirtual void() enf4tur_atk6 = [$attack6, enf4tur_atk7]
{
atk_lightning ();
};
- nonvirtual void() enf4turret_atk7 = [$attack6, enf4turret_atk8]
+ nonvirtual void() enf4tur_atk7 = [$attack6, enf4tur_atk8]
{
atk_lightning ();
};
- nonvirtual void() enf4turret_atk8 = [$attack6, enf4turret_atk9]
+ nonvirtual void() enf4tur_atk8 = [$attack6, enf4tur_atk9]
{
atk_lightning ();
};
- nonvirtual void() enf4turret_atk9 = [$attack7, enf4turret_atk10] {ai_face();};
- nonvirtual void() enf4turret_atk10 = [$attack8, enf4turret_atk11] {ai_face();};
- nonvirtual void() enf4turret_atk11 = [$attack9, enf4turret_atk12] {ai_face();};
- nonvirtual void() enf4turret_atk12 = [$attack10, enf2stand1]
+ nonvirtual void() enf4tur_atk9 = [$attack7, enf4tur_atk10] {ai_face();};
+ nonvirtual void() enf4tur_atk10 = [$attack8, enf4tur_atk11]{ai_face();};
+ nonvirtual void() enf4tur_atk11 = [$attack9, enf4tur_atk12]{ai_face();};
+ nonvirtual void() enf4tur_atk12 = [$attack10, enf2stand1]
{
ai_face ();
- sub_checkrefire (enf2turret_atk1);
+ sub_checkrefire (enf2tur_atk1);
};
//--------------------------------------------------------------
@@ -856,7 +865,7 @@ class monster_enforcer: base_walkmonster
{
if (this.spawnflags & I_AM_TURRET)
{
- this.think_turret = this.enf2turret_atk1;
+ this.think_turret = this.enf2tur_atk1;
}
this.think_missile = this.enf2atk1;
}
@@ -864,7 +873,7 @@ class monster_enforcer: base_walkmonster
{
if (this.spawnflags & I_AM_TURRET)
{
- this.think_turret = this.turret_atk1;
+ this.think_turret = this.tur_atk1;
}
this.think_missile = this.atk1;
}
@@ -872,7 +881,7 @@ class monster_enforcer: base_walkmonster
{
if (this.spawnflags & I_AM_TURRET)
{
- this.think_turret = this.enf4turret_atk1;
+ this.think_turret = this.enf4tur_atk1;
}
this.think_missile = this.enf4atk1;
}
@@ -889,361 +898,9 @@ class monster_enforcer: base_walkmonster
};
//==============================================================================
-// TODO CEV: rework the enforcer attack / projectile functions below
+// Scenic Dead Monster Patch stuff here from DeadStuff mod -- dumptruck_ds
//==============================================================================
-void(vector org, vector vec) EnfLaunchSpike =
-{
-
- local float projspeed = self.proj_speed_mod * 600;
-
- sound_attack (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
-
- vec = normalize (vec);
-
- newmis = spawn ();
- newmis.owner = self;
- newmis.movetype = MOVETYPE_FLY;
- newmis.solid = SOLID_BBOX;
- // newmis.effects = EF_DIMLIGHT;
- // dumptruck_ds
- newmis.skin = self.skin_proj;
- // setmodel (newmis, "progs/s_spike.mdl");
-
- // dumptruck_ds
- if (self.mdl_proj != "")
- {
- setmodel (newmis, self.mdl_proj);
- }
- else
- {
- setmodel (newmis, "progs/s_spike.mdl");
- }
-
- // dumptruck_ds
- if (!newmis.skin_proj)
- {
- newmis.skin = self.skin_proj;
- }
- else
- {
- newmis.skin = 0;
- }
- // dumptruck_ds - end
-
- setsize (newmis, '0 0 0', '0 0 0');
-
- setorigin (newmis, org);
-
- SetSpeed (newmis, vec, projspeed);
- newmis.angles = vectoangles (newmis.velocity);
-
- if (self.homing > 0)
- {
- SetupHoming (newmis, projspeed);
- }
- else
- {
- newmis.nextthink = time + 5;
- newmis.think = sub_remove;
- }
- newmis.touch = superspike_touch;
-};
-
-// dumptruck_ds start
-// from inside qc tut http://www.insideqc.com/qctut/lesson-32.shtml
-void() EnfMisTouch =
-{
- local float damg;
-
- if (other == self.owner)
- // don't explode on owner
- return;
-
- if (pointcontents(self.origin) == CONTENT_SKY)
- {
- remove (self);
- return;
- }
-
- // dumptruck_ds
- damg = 30 + random() * 2;
-
- if (other.health)
- {
- if (other.classname == "monster_shambler")
- // mostly immune
- damg = damg * 0.5;
- T_Damage (other, self, self.owner, damg );
- }
-
- // don't do radius damage to the other, because all the damage
- // was done in the impact
- // dumptruck_ds
- T_RadiusDamage (self, self.owner, 40, other);
-
- // sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
- self.origin = self.origin - 8 * normalize(self.velocity);
-
- 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);
-
- // BecomeExplosion
- spawn (base_explosion, origin: self.origin);
- remove (self);
-};
-
-//----------------------------------------------------------------------
-// EnfRocket
-// dumptruck_ds start -- from inside qc tut
-// http://www.insideqc.com/qctut/lesson-32.shtml
-//----------------------------------------------------------------------
-void() EnfRocket =
-{
- local entity missile;
- local float projspeed = 900 * self.proj_speed_mod;
- // dumptruck_ds
- // self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-
- sound_attack (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 -- dumptruck_ds below
-
- SetSpeed (missile, normalize(self.enemy.origin - self.origin),
- projspeed);
- missile.angles = vectoangles (missile.velocity);
- missile.touch = EnfMisTouch;
-
- // makevectors (self.v_angle);
- // missile.velocity = aim(self, 1000);
- // missile.velocity = missile.velocity * 1000;
- // missile.angles = vectoangles(missile.velocity);
-
- // missile.touch = T_MissileTouch;
-
- // set missile duration
- if (self.homing > 0)
- {
- SetupHoming (missile, projspeed);
- }
- else
- {
- missile.nextthink = time + 5;
- missile.think = sub_remove;
- }
- // dumptruck_ds
- missile.skin = self.skin_proj;
-
- // dumptruck_ds
- if (self.mdl_proj != "")
- {
- setmodel (missile, self.mdl_proj);
- }
- else
- {
- setmodel (missile, "progs/missile.mdl");
- }
-
- // dumptruck_ds
- if (!missile.skin_proj)
- {
- missile.skin = self.skin_proj;
- }
- else
- {
- missile.skin = 0;
- }
- // dumptruck_ds - end
-
- // setmodel (missile, "progs/missile.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- // thanks Voidforce -- dumptruck_ds
- makevectors (self.angles);
- // last number was 16 - dumptruck_ds
- setorigin (missile, self.origin + v_forward * 30 +
- v_right * 8.5 + '0 0 12');
- // setorigin (missile, self.origin + v_forward*8 + '0 0 16');
-};
-// end dumptruck_ds grunt missle end
-
-//----------------------------------------------------------------------
-// EnfFireGrenade
-//----------------------------------------------------------------------
-void() EnfFireGrenade =
-{
- local entity missile;
-
- self.effects = self.effects | EF_MUZZLEFLASH;
-
- sound_attack (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_BBOX;
-
- // set missile speed
- makevectors (self.angles);
-
- missile.velocity = normalize (self.enemy.origin - self.origin);
- missile.velocity = missile.velocity * 600;
- missile.velocity_z = 200;
-
- missile.avelocity = '300 300 300';
-
- missile.angles = vectoangles (missile.velocity);
-
- missile.touch = OgreGrenadeTouch;
-
- // set missile duration
- missile.nextthink = time + 2.5;
- missile.think = OgreGrenadeExplode;
- // dumptruck_ds
- missile.skin = self.skin_proj;
-
- // dumptruck_ds
- if (self.mdl_proj != "")
- {
- setmodel (missile, self.mdl_proj);
- }
- else
- {
- setmodel (missile, "progs/grenade.mdl");
- }
-
- // dumptruck_ds
- if (!missile.skin_proj)
- {
- missile.skin = self.skin_proj;
- }
- else
- {
- missile.skin = 0;
- }
- // dumptruck_ds - end
-
- // setmodel (missile, "progs/grenade.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin + v_forward * 30 +
- v_right * 8.5 + '0 0 16');
- // setorigin (missile, self.origin);
-};
-
-//==============================================================================
-
-void() Laser_Touch =
-{
- local vector org;
-
- // don't explode on owner
- if (other == self.owner)
- return;
-
- if (pointcontents(self.origin) == CONTENT_SKY)
- {
- remove (self);
- return;
- }
-
- // dumptruck_ds
- sound_hit (self, CHAN_WEAPON, "enforcer/enfstop.wav", 1, ATTN_STATIC);
- org = self.origin - 8 * normalize (self.velocity);
-
- if (other.health)
- {
- SpawnBlood (org, self.velocity * 0.2, 15);
- T_Damage (other, self, self.owner, 15);
- }
- else
- {
- 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);
- }
-
- remove (self);
-};
-
-void(vector org, vector vec) LaunchLaser =
-{
-
- local float projspeed = self.proj_speed_mod * 600;
-
- if (self.classname == "monster_enforcer" ||
- self.classname == "monster_army")
- {
- sound_attack (self, CHAN_WEAPON, "enforcer/enfire.wav",
- 1, ATTN_NORM);
- }
-
- vec = normalize (vec);
-
- newmis = spawn ();
- // dumptruck_ds
- newmis.snd_hit = self.snd_hit;
- newmis.owner = self;
- newmis.movetype = MOVETYPE_FLY;
- newmis.solid = SOLID_BBOX;
- newmis.effects = EF_DIMLIGHT;
- // dumptruck_ds
- newmis.skin = self.skin_proj;
-
- // dumptruck_ds
- if (self.mdl_proj != "")
- {
- setmodel (newmis, self.mdl_proj);
- }
- else
- {
- setmodel (newmis, "progs/laser.mdl");
- }
-
- // dumptruck_ds
- if (!newmis.skin_proj)
- {
- newmis.skin = self.skin_proj;
- }
- else
- {
- newmis.skin = 0;
- }
-
- // setmodel (newmis, "progs/laser.mdl");
- setsize (newmis, '0 0 0', '0 0 0');
-
- setorigin (newmis, org);
-
- SetSpeed (newmis, vec, projspeed);
- newmis.angles = vectoangles (newmis.velocity);
- if (self.homing > 0)
- {
- SetupHoming (newmis, projspeed);
- }
- else
- {
- newmis.nextthink = time + 5;
- newmis.think = sub_remove;
- }
- newmis.touch = Laser_Touch;
-};
-
-//==============================================================================
-
-/* Scenic Dead Monster Patch stuff here from DeadStuff mod -- dumptruck_ds */
-
/*QUAKED monster_dead_enforcer (0 0.5 0.8) (-16 -16 -24) (16 16 32) SOLID FACE_UP X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
{
model ({"path":"progs/enforcer.mdl","frame":54});
Return to the top of this page or return to the overview of this repo.
Diff qc/monsters/fish.qc
diff --git a/qc/monsters/fish.qc b/qc/monsters/fish.qc
index 1c6a780..15a8331 100644
--- a/qc/monsters/fish.qc
+++ b/qc/monsters/fish.qc
@@ -97,7 +97,7 @@ class monster_fish: base_swimmonster
sound_attack (this, CHAN_VOICE, "fish/bite.wav", 1, ATTN_NORM);
ldmg = (random() + random()) * 3;
- T_Damage (this.enemy, this, this, ldmg);
+ this.t_damage2 (this.enemy, this, this, ldmg);
};
//--------------------------------------------------------------
Return to the top of this page or return to the overview of this repo.
Diff qc/monsters/hknight.qc
diff --git a/qc/monsters/hknight.qc b/qc/monsters/hknight.qc
index 462aa2a..bea364b 100644
--- a/qc/monsters/hknight.qc
+++ b/qc/monsters/hknight.qc
@@ -208,7 +208,7 @@ class monster_hell_knight: base_walkmonster
WriteCoord (MSG_BROADCAST, trace_endpos_y);
WriteCoord (MSG_BROADCAST, trace_endpos_z);
- LightningDamage (org, trace_endpos, this, 20);
+ weapon_lightning::lightning_damage (org, trace_endpos, this, 20);
};
//--------------------------------------------------------------
@@ -240,11 +240,7 @@ class monster_hell_knight: base_walkmonster
//--------------------------------------------------------------
nonvirtual void(float offset) attack_shot =
{
- local vector offang, org, vec;
-
- local float exploding = this.projexpl == 1 ||
- (this.projexpl == 2 && offset % 2 == 0) ||
- (this.projexpl == 3 && random()*2 < 1);
+ local vector offang, org;
offang = vectoangles (this.enemy.origin - this.origin);
offang_y = offang_y + offset * 6;
@@ -254,47 +250,7 @@ class monster_hell_knight: base_walkmonster
org = this.origin + this.mins + this.size * 0.5 +
v_forward * 20;
- // set missile speed
- vec = normalize (v_forward);
- vec_z = 0 - vec_z + (random() - 0.5) * 0.1;
-
- launch_spike2 (org, vec, 300);
- newmis.classname = "knightspike";
- // setmodel (newmis, "progs/k_spike.mdl");
- if (exploding)
- {
- // TODO CEV
- newmis.touch = T_HellKnightMisTouch;
- // dumptruck_ds custom_mdls
- if (this.mdl_exproj != "")
- setmodel (newmis, this.mdl_exproj);
- else
- setmodel (newmis, "progs/k_spike2.mdl");
-
- // dumptruck_ds
- if (this.skin_exproj)
- newmis.skin = this.skin_exproj;
- else
- newmis.skin = 0;
- }
- else
- {
- // dumptruck_ds custom_mdls
- if (this.mdl_proj != "")
- setmodel (newmis, this.mdl_proj);
- else
- setmodel (newmis, "progs/k_spike.mdl");
-
- // dumptruck_ds
- if (this.skin_proj)
- newmis.skin = this.skin_proj;
- else
- newmis.skin = 0;
- }
-
- setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
- sound_attack (this, CHAN_WEAPON, "hknight/attack1.wav",
- 1, ATTN_NORM);
+ fire_hknightspell (org, v_forward, offset);
};
//--------------------------------------------------------------
Return to the top of this page or return to the overview of this repo.
Diff qc/monsters/ogre.qc
diff --git a/qc/monsters/ogre.qc b/qc/monsters/ogre.qc
index cf1d10e..3a21fdc 100644
--- a/qc/monsters/ogre.qc
+++ b/qc/monsters/ogre.qc
@@ -7,254 +7,9 @@
//======================================================================
const float MONSTER_FLAK_OGRE = 4;
const float FL_NOSELECT = 8192; // ignored by entity selector
-
-const float OGRE_G_VEL = 600; // speed an ogre grenade is fired at
-const float pgrav = 800; // TODO: get correct grav for level
const float OGRE_DEFAULT_ELEVATION = 30;// angle to fire at if enemy too far
//======================================================================
-// fields
-//======================================================================
-
-// bdw - saves up flak hits to do a single damage next frame -
-// currently only used for flak ogre
-.float spikecount;
-
-//======================================================================
-
-// TODO CEV generalize & rework projectiles
-
-void() OgreGrenadeExplode =
-{
- T_RadiusDamage (self, self.owner, 40, world);
- sound (self, CHAN_VOICE, "weapons/r_exp3.wav", 1, ATTN_NORM);
-
- 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);
-
- // BecomeExplosion
- spawn (base_explosion, origin: self.origin);
- remove (self);
-};
-
-void() OgreGrenadeTouch =
-{
- if (other == self.owner)
- // don't explode on owner
- return;
-
- if (other.takedamage == DAMAGE_AIM)
- {
- OgreGrenadeExplode ();
- return;
- }
-
- if (self.count < time)
- {
- // bounce sound
- sound (self, CHAN_VOICE, "weapons/bounce.wav", 1, ATTN_NORM);
- }
- self.count = time + .02;
-
- if (self.velocity == '0 0 0')
- self.avelocity = '0 0 0';
-};
-
-//======================================================================
-
-// TODO CEV generalize & rework projectiles
-
-// BDW 31/08/00 - evil, nasty red-hot nail cluster-bomb attack...
-// from Marcher -- dumptruck_ds
-void() FlakDoDamage =
-{
- // get correct gib direction
- self.origin = self.oldenemy.origin + self.oldorigin;
- T_Damage (self.oldenemy, self, self.owner, self.oldenemy.spikecount);
- self.oldenemy.spikecount = 0;
- remove (self);
-};
-
-void() FlakTouch =
-{
- if (other.solid == SOLID_TRIGGER)
- return;
-
- if (pointcontents(self.origin) == CONTENT_SKY)
- {
- remove (self);
- return;
- }
-
- // hit something that bleeds
- if (other.takedamage)
- {
- spawn_touchblood(self.dmg);
-
- sound(self, CHAN_VOICE, "fish/bite.wav", 1, ATTN_NORM);
-
- if (other.spikecount)
- {
- // not the first one
- other.spikecount = other.spikecount + self.dmg;
- remove(self);
- return;
- }
-
- // the first one...
- other.spikecount = self.dmg;
-
- // stick around for a little while...
- self.velocity = '0 0 0';
- self.solid = SOLID_NOT;
- self.touch = sub_null;
- self.model = string_null;
- // displacement from enemy origin (its gonna move next frame)
- self.oldorigin = self.origin - other.origin;
- self.oldenemy = other;
- self.think = FlakDoDamage;
- self.nextthink = time + 0.05;
- return;
- }
-
- 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);
-
- // bit of a hack
- if (self.spawnflags & MONSTER_FLAK_OGRE)
- {
- remove (self);
- return;
- }
-
- // gets weaker with each bounce. also stops them getting stuck in world.
- self.dmg = self.dmg - 5;
- if (self.dmg <= 0)
- {
- remove (self);
- return;
- }
- // reduce crazy ricochets
- self.velocity = self.velocity * 0.5;
- self.movetype = MOVETYPE_BOUNCE;
-};
-
-//======================================================================
-
-// TODO CEV generalize & rework projectiles
-
-//----------------------------------------------------------------------
-// Multi Grenade Code from doe progs MULT_WPN.QC -- dumptruck_ds
-//----------------------------------------------------------------------
-
-//----------------------------------------------------------------------
-void() MiniGrenadeExplode =
-{
- if ( self.owner.classname == "player")
- T_RadiusDamage (self, self.owner, 90, world);
- else
- T_RadiusDamage (self, self.owner, 60, world);
-
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, TE_EXPLOSION2);
- WriteCoord (MSG_BROADCAST, self.origin_x);
- WriteCoord (MSG_BROADCAST, self.origin_y);
- WriteCoord (MSG_BROADCAST, self.origin_z);
- WriteByte (MSG_BROADCAST, 230);
- WriteByte (MSG_BROADCAST, 5);
-
- // BecomeExplosion
- spawn (base_explosion, origin: self.origin);
- remove (self);
-};
-
-//----------------------------------------------------------------------
-void(float offsetAngle) MiniGrenadeLaunch =
-{
- local entity missile/*, mpuff*/;
- local float tempRand;
-
- missile = spawn ();
- missile.owner = self.owner;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_BBOX;
- missile.classname = "MiniGrenade";
-
- // set missile speed
- missile.v_angle = self.v_angle;
- missile.v_angle_y = missile.v_angle_y + offsetAngle;
- makevectors (missile.v_angle);
-
- missile.velocity = v_forward * 100 + v_up * 400;
- tempRand = (crandom() * 60) - 30;
- missile.velocity = missile.velocity + tempRand * v_forward;
- tempRand = (crandom() * 40) - 20;
- missile.velocity = missile.velocity + tempRand * v_right;
- tempRand = (crandom() * 60) - 30;
- missile.velocity = missile.velocity + tempRand * v_up;
-
- missile.avelocity = '300 300 300';
- missile.angles = vectoangles (missile.velocity);
- missile.touch = MultiGrenadeTouch;
-
- setmodel (missile, "progs/mervup.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin);
-
- // set missile duration
- missile.nextthink = time + 1 + (crandom() * 0.5);
- missile.think = MiniGrenadeExplode;
-};
-
-//----------------------------------------------------------------------
-void() MultiGrenadeExplode =
-{
- MiniGrenadeLaunch (0);
- MiniGrenadeLaunch (72);
- MiniGrenadeLaunch (144);
- MiniGrenadeLaunch (216);
- MiniGrenadeLaunch (288);
-
- remove (self);
-};
-
-//----------------------------------------------------------------------
-void() MultiGrenadeTouch =
-{
- if (other == self.owner)
- // don't explode on owner
- return;
-
- if (other.takedamage == DAMAGE_AIM)
- {
- if (self.classname == "MiniGrenade")
- MiniGrenadeExplode ();
- else
- {
- if (self.owner.classname == "player")
- GrenadeExplode ();
- else
- MiniGrenadeExplode ();
- }
- return;
- }
- // bounce sound
- sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
- if (self.velocity == '0 0 0')
- self.avelocity = '0 0 0';
-};
-
-//----------------------------------------------------------------------
-// end doe qc -- dumptruck_ds
-//----------------------------------------------------------------------
-
-//======================================================================
// frame macros
//======================================================================
$cd id1/models/ogre_c
@@ -399,7 +154,7 @@ class monster_ogre: base_walkmonster
if (enemy_range == RANGE_MELEE)
{
- if (CanDamage (this.enemy, this))
+ if (this.can_damage(this, this.enemy))
{
this.attack_state = AS_MELEE;
return TRUE;
@@ -454,391 +209,66 @@ class monster_ogre: base_walkmonster
};
//--------------------------------------------------------------
- // BDW_OgreFireFlak
- //--------------------------------------------------------------
- nonvirtual void() attack_flak =
- {
- local float flakcount;
- local vector dir, ang;
- local entity flak;
- local float projspeed = 800 * this.proj_speed_mod;
-
- flakcount = 8;
-
- this.effects = this.effects | EF_MUZZLEFLASH;
- sound (this, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
-
- // make angles out of the current displacement vector...
- ang = vectoangles (this.enemy.origin - this.origin);
- // then get the required components...
- makevectors (ang);
-
- while (flakcount > 0)
- {
- //tighter spread...
- dir = v_forward * 10 + crandom() *
- v_right + crandom() * v_up;
- dir = normalize (dir);
- // f*cking hack...is this a v_forward problem?
- dir_z = dir_z * -1;
- // dir = dir * 1000;
- // dir = dir * 800;
-
- flak = spawn ();
- flak.owner = this;
- // flymissile is a bit too all-seeing for this gun...
- flak.movetype = MOVETYPE_FLY;
- // flak.movetype = MOVETYPE_FLYMISSILE;
- flak.solid = SOLID_BBOX;
- flak.flags = FL_NOSELECT;
- flak.touch = FlakTouch;
- flak.angles = vectoangles (dir);
- SetSpeed (flak, dir, projspeed);
- if (this.homing > 0)
- {
- SetupHoming (flak, projspeed);
- }
- else
- {
- flak.nextthink = time + 6;
- flak.think = sub_remove;
- }
- flak.dmg = 4;
-
- // this is a hack to tell FlakTouch that it came
- // from an ogre
- flak.spawnflags = MONSTER_FLAK_OGRE;
- // setmodel (flak, "progs/spike.mdl");
- // dumptruck_ds
- flak.skin = this.skin_proj;
-
- // dumptruck_ds
- if (this.mdl_proj != "")
- {
- setmodel (flak, this.mdl_proj);
- }
- else
- {
- setmodel (flak, "progs/spike.mdl");
- }
-
- // dumptruck_ds
- if (!flak.skin_proj)
- {
- flak.skin = this.skin_proj;
- }
- else
- {
- flak.skin = 0;
- }
- // dumptruck_ds - end
-
- setsize (flak, '0 0 0', '0 0 0');
- setorigin (flak, this.origin + '0 0 16');
-
- flakcount = flakcount - 1;
- }
- };
-
- //--------------------------------------------------------------
- // OgreFireGrenade
- //--------------------------------------------------------------
- nonvirtual void() attack_grenade =
- {
- local entity missile;
-
- this.effects = this.effects | EF_MUZZLEFLASH;
-
- sound (this, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
-
- missile = spawn ();
- missile.owner = this;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_BBOX;
- // dumptruck_ds
- missile.skin = this.skin_proj;
-
- // dumptruck_ds
- if (this.mdl_proj != "")
- {
- setmodel (missile, this.mdl_proj);
- }
- else
- {
- setmodel (missile, "progs/grenade.mdl");
- }
-
- // dumptruck_ds
- if (!missile.skin_proj)
- {
- missile.skin = this.skin_proj;
- }
- else
- {
- missile.skin = 0;
- }
- // dumptruck_ds - end
-
- // set missile speed
- makevectors (this.angles);
- missile.velocity = normalize (this.enemy.origin - this.origin);
- missile.velocity = missile.velocity * 600;
- missile.velocity_z = 200;
- missile.avelocity = '300 300 300';
- missile.angles = vectoangles (missile.velocity);
-
- // set missile duration
- if (this.style == 3)
- {
- missile.touch = MultiGrenadeTouch;
- missile.nextthink = time + 2.5;
- missile.think = MultiGrenadeExplode;
- setmodel (missile, "progs/mervup.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, this.origin);
- missile.classname = "MultiGrenade";
- }
- else
- {
- missile.touch = OgreGrenadeTouch;
- missile.nextthink = time + 2.5;
- missile.think = OgreGrenadeExplode;
- // setmodel (missile, "progs/grenade.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, this.origin);
- }
-
- // missile.touch = OgreGrenadeTouch;
-
- // set missile duration
- // missile.nextthink = time + 2.5;
- // missile.think = OgreGrenadeExplode;
- //
- // setmodel (missile, "progs/grenade.mdl");
- // setsize (missile, '0 0 0', '0 0 0');
- // setorigin (missile, self.origin);
- };
-
- //--------------------------------------------------------------
- // PreachFireGrenade
- //--------------------------------------------------------------
- nonvirtual void(float elevation) attack_preach_grenade =
- {
- local entity missile;
- local vector ang;
-
- this.effects = this.effects | EF_MUZZLEFLASH;
-
- sound (this, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
-
- missile = spawn ();
- missile.owner = this;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_BBOX;
-
- // set missile speed
- ang = this.angles;
- 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;
-
- // set missile duration
- missile.nextthink = time + 2.5;
- missile.think = OgreGrenadeExplode;
- // setmodel (missile, "progs/grenade.mdl");
- // dumptruck_ds
- if (this.mdl_proj != "")
- {
- setmodel (missile, this.mdl_proj);
- }
- else
- {
- setmodel (missile, "progs/grenade.mdl");
- }
-
- // dumptruck_ds
- if (!missile.skin_proj)
- {
- missile.skin = this.skin_proj;
- }
- else
- {
- missile.skin = 0;
- }
-
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, this.origin);
- };
-
- //--------------------------------------------------------------
// OgreFireSpike from insideqc tutorial here:
// http://www.insideqc.com/qctut/lesson-33.shtml
//--------------------------------------------------------------
nonvirtual void() attack_spike =
{
- local vector dir;
- // local entity old;
-
sound (this, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
+ this.effects = this.effects | EF_MUZZLEFLASH;
+
this.attack_finished = time + 0.7;
// this.attack_finished = time + 0.2;
// -- dumptruck_ds
- this.effects = this.effects | EF_MUZZLEFLASH;
-
- dir = normalize (this.enemy.origin - this.origin);
-
- launch_spike (this.origin + v_right * 4 + '0 0 16', dir);
- // dumptruck_ds found in client.qc
- newmis.touch = superduperspike_touch;
- // setmodel (newmis, "progs/lspike.mdl");
- // dumptruck_ds
- newmis.skin = this.skin_proj;
-
- // dumptruck_ds
- if (this.mdl_proj != "")
- {
- setmodel (newmis, this.mdl_proj);
- }
- else
- {
- setmodel (newmis, "progs/lspike.mdl");
- }
-
- // dumptruck_ds
- if (!newmis.skin_proj)
- {
- newmis.skin = this.skin_proj;
- }
- else
- {
- newmis.skin = 0;
- }
- // dumptruck_ds - end
-
- setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
+ // when was makevectors last called? -- CEV
+ makevectors (this.angles);
+ fire_spike (this.origin + v_right * 4 + '0 0 16',
+ this.enemy.origin - this.origin, SPIKE_DUPER_DAMAGE,
+ SPIKE_SPEED);
};
//--------------------------------------------------------------
- // W_FireMultiGrenade
+ // OgreFireLavaBall by jaycie erysdren 2021-09-14
//--------------------------------------------------------------
- nonvirtual void() attack_multigrenade =
+ nonvirtual void() attack_lavaball =
{
- // local entity missile, mpuff;
- local entity missile;
-
- // this.currentammo = this.ammo_multi_rockets =
- // this.ammo_multi_rockets - 1;
- // UpdateAmmoCounts (this);
+ makevectors (vectoangles(this.enemy.origin - this.origin));
- sound (this, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
-
- // this.punchangle_x = -2;
-
- missile = spawn ();
- missile.owner = this;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_BBOX;
- missile.classname = "MultiGrenade";
-
- makevectors (this.angles);
- missile.velocity = normalize (this.enemy.origin - this.origin);
- missile.velocity = missile.velocity * 600;
- missile.velocity_z = 200;
- missile.avelocity = '300 300 300';
- missile.angles = vectoangles (missile.velocity);
-
- // set missile speed
- // makevectors (this.v_angle);
- // if (this.v_angle_x)
- // missile.velocity = v_forward * 600 + v_up * 200 +
- // crandom() * v_right * 10 + crandom() * v_up * 10;
- // else
- // {
- // missile.velocity = aim (this, 10000);
- // missile.velocity = missile.velocity * 600;
- // missile.velocity_z = 200;
- // }
- //
- // missile.avelocity = '300 300 300';
- // missile.angles = vectoangles (missile.velocity);
-
- missile.touch = MultiGrenadeTouch;
-
- // set missile duration
- missile.nextthink = time + 1;
- missile.think = MultiGrenadeExplode;
- setmodel (missile, "progs/mervup.mdl");
- // dumptruck_ds
- missile.skin = this.skin_proj;
+ this.effects = this.effects | EF_MUZZLEFLASH;
+ sound_attack (this, CHAN_AUTO, "boss1/throw.wav", 1, ATTN_NORM);
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, this.origin + '0 0 16');
+ // damage should be 40, 40 -- TODO CEV
+ // custom lavaball speed -- CEV
+ fire_lavaball (this.origin + v_right * 4 + '0 0 16',
+ this.enemy.origin - this.origin, 600);
};
//--------------------------------------------------------------
- // OgreFireLavaBall by jaycie erysdren 2021-09-14
- //--------------------------------------------------------------
- nonvirtual void() attack_lavaball =
+ nonvirtual void() attack_ranged =
{
- local vector offang;
- local vector org, vec, d;
- // local float t;
-
- offang = vectoangles (this.enemy.origin - this.origin);
- makevectors (offang);
-
- org = this.origin;
- // + p_x*v_forward + p_y*v_right + p_z*'0 0 1';
-
- // lead the player on hard mode
- // if (skill > 1)
- // {
- // t = vlen(this.enemy.origin - org) / 300;
- // vec = this.enemy.velocity;
- // vec_z = 0;
- // d = this.enemy.origin + t * vec;
- // }
- // else
- // {
- d = this.enemy.origin;
- // }
-
- vec = normalize (d - org);
-
- // launch_spike (org, vec);
- launch_spike2 (this.origin + v_right * 4 + '0 0 16', vec, 600);
- this.effects = this.effects | EF_MUZZLEFLASH;
- // dumptruck_ds custom_mdls
- if (this.mdl_proj != "")
- {
- setmodel (newmis, this.mdl_proj);
- }
- else
- {
- setmodel (newmis, "progs/lavaball.mdl");
- }
-
- // dumptruck_ds
- if (!newmis.skin_proj)
+ switch (this.style)
{
- newmis.skin = this.skin_proj;
+ case 0:
+ fire_grenade (this.origin, 40, 40, 0);
+ break;
+ case 1:
+ fire_flak (this.origin + '0 0 16', 800);
+ break;
+ case 2:
+ attack_spike ();
+ break;
+ case 3:
+ fire_multigrenade ();
+ break;
+ case 4:
+ attack_lavaball ();
+ // used for initial attack sound dumptruck_ds
+ sound_misc2 (this, CHAN_WEAPON,
+ "shalrath/attack2.wav",
+ 1, ATTN_NORM);
+ break;
}
- else
- {
- newmis.skin = 0;
- }
- newmis.avelocity = this.cust_avelocity;
- if !(newmis.avelocity)
- newmis.avelocity = '200 100 300';
- setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
- // newmis.touch = T_MissileTouch; // rocket explosion
- newmis.touch = OgreGrenadeExplode;
- sound_attack (this, CHAN_AUTO, "boss1/throw.wav", 1, ATTN_NORM);
};
//--------------------------------------------------------------
@@ -851,7 +281,7 @@ class monster_ogre: base_walkmonster
if (!this.enemy)
return;
- if (!CanDamage (this.enemy, this))
+ if (!this.can_damage(this, this.enemy))
return;
ai_charge (10);
@@ -862,7 +292,7 @@ class monster_ogre: base_walkmonster
return;
ldmg = (random() + random() + random()) * 4;
- T_Damage (this.enemy, this, this, ldmg);
+ this.t_damage2 (this.enemy, this, this, ldmg);
if (side)
{
@@ -1065,30 +495,7 @@ class monster_ogre: base_walkmonster
nonvirtual void() nail4 = [$shoot3, nail5]
{
ai_face ();
- if (this.style == 0)
- {
- this.attack_grenade ();
- }
- if (this.style == 1)
- {
- this.attack_flak ();
- }
- else if (this.style == 2)
- {
- this.attack_spike ();
- }
- if (this.style == 3)
- {
- this.attack_multigrenade ();
- }
- if (this.style == 4)
- {
- // jaycie erysdren 2021-09-14
- this.attack_lavaball ();
- // used for initial attack sound dumptruck_ds
- sound_misc2 (this, CHAN_WEAPON, "shalrath/attack2.wav",
- 1, ATTN_NORM);
- }
+ this.attack_ranged ();
};
nonvirtual void() nail5 = [$shoot4, nail6] { ai_face (); };
nonvirtual void() nail6 = [$shoot5, nail7] { ai_face (); };
@@ -1101,61 +508,38 @@ class monster_ogre: base_walkmonster
//--------------------------------------------------------------
// Ogre Turret Attack
//--------------------------------------------------------------
- nonvirtual void() turret_atk1 = [$shoot1, turret_atk2] { ai_face (); };
- nonvirtual void() turret_atk2 = [$shoot2, turret_atk3] { ai_face (); };
- nonvirtual void() turret_atk3 = [$shoot2, turret_atk4] { ai_face (); };
- nonvirtual void() turret_atk4 = [$shoot3, turret_atk5]
+ nonvirtual void() tur_atk1 = [$shoot1, tur_atk2] { ai_face (); };
+ nonvirtual void() tur_atk2 = [$shoot2, tur_atk3] { ai_face (); };
+ nonvirtual void() tur_atk3 = [$shoot2, tur_atk4] { ai_face (); };
+ nonvirtual void() tur_atk4 = [$shoot3, tur_atk5]
{
ai_face ();
- if (this.style == 0)
- {
- this.attack_grenade ();
- }
- if (this.style == 1)
- {
- this.attack_flak ();
- }
- else if (this.style == 2)
- {
- this.attack_spike ();
- }
- if (this.style == 3)
- {
- this.attack_multigrenade ();
- }
- if (this.style == 4)
- {
- // jaycie erysdren 2021-09-14
- this.attack_lavaball ();
- // used for initial attack sound dumptruck_ds
- sound_misc2 (this, CHAN_WEAPON, "shalrath/attack2.wav",
- 1, ATTN_NORM);
- }
+ attack_ranged ();
};
- nonvirtual void() turret_atk5 = [$shoot4, turret_atk6] { ai_face (); };
- nonvirtual void() turret_atk6 = [$shoot5, turret_atk7] { ai_face (); };
- nonvirtual void() turret_atk7 = [$shoot5, turret_atk8] { ai_face (); };
- nonvirtual void() turret_atk8 = [$shoot6, turret_atk9] { ai_face (); };
- nonvirtual void() turret_atk9 = [$shoot6, turret_seek1] { ai_face (); };
+ nonvirtual void() tur_atk5 = [$shoot4, tur_atk6] { ai_face (); };
+ nonvirtual void() tur_atk6 = [$shoot5, tur_atk7] { ai_face (); };
+ nonvirtual void() tur_atk7 = [$shoot5, tur_atk8] { ai_face (); };
+ nonvirtual void() tur_atk8 = [$shoot6, tur_atk9] { ai_face (); };
+ nonvirtual void() tur_atk9 = [$shoot6, tur_seek1] { ai_face (); };
//--------------------------------------------------------------
// Ogre Turret Seek / Stand
//--------------------------------------------------------------
- nonvirtual void() turret_seek1 = [$stand1, turret_seek2] { ai_run (0);};
- nonvirtual void() turret_seek2 = [$stand2, turret_seek3] { ai_run (0);};
- nonvirtual void() turret_seek3 = [$stand3, turret_seek4] { ai_run (0);};
- nonvirtual void() turret_seek4 = [$stand4, turret_seek5] { ai_run (0);};
- nonvirtual void() turret_seek5 = [$stand5, turret_seek6]
+ nonvirtual void() tur_seek1 = [$stand1, tur_seek2] { ai_run (0);};
+ nonvirtual void() tur_seek2 = [$stand2, tur_seek3] { ai_run (0);};
+ nonvirtual void() tur_seek3 = [$stand3, tur_seek4] { ai_run (0);};
+ nonvirtual void() tur_seek4 = [$stand4, tur_seek5] { ai_run (0);};
+ nonvirtual void() tur_seek5 = [$stand5, tur_seek6]
{
if (random() < 0.2)
sound_idle (this, CHAN_VOICE, "ogre/ogidle.wav",
1, ATTN_IDLE);
ai_run (0);
};
- nonvirtual void() turret_seek6 = [$stand6, turret_seek7] { ai_run (0);};
- nonvirtual void() turret_seek7 = [$stand7, turret_seek8] { ai_run (0);};
- nonvirtual void() turret_seek8 = [$stand8, turret_seek9] { ai_run (0);};
- nonvirtual void() turret_seek9 = [$stand9, turret_seek1] { ai_run (0);};
+ nonvirtual void() tur_seek6 = [$stand6, tur_seek7] { ai_run (0);};
+ nonvirtual void() tur_seek7 = [$stand7, tur_seek8] { ai_run (0);};
+ nonvirtual void() tur_seek8 = [$stand8, tur_seek9] { ai_run (0);};
+ nonvirtual void() tur_seek9 = [$stand9, tur_seek1] { ai_run (0);};
/////////////////////////
// turret frames END //
@@ -1255,7 +639,7 @@ class monster_ogre: base_walkmonster
// default Ogre
this.ammo_rockets = 2;
}
- if(!this.keep_ammo)
+ if (!this.keep_ammo)
item_backpack::drop_backpack (this.origin, this.weapon,
this.ammo_shells, this.ammo_nails,
this.ammo_rockets, this.ammo_cells);
@@ -1485,7 +869,7 @@ class monster_ogre: base_walkmonster
this.think_walk = this.walk1;
if (this.spawnflags & I_AM_TURRET)
{
- this.think_run = this.turret_seek1;
+ this.think_run = this.tur_seek1;
}
else
{
@@ -1495,7 +879,7 @@ class monster_ogre: base_walkmonster
this.think_melee = this.attack_melee;
this.think_missile = this.nail1;
// dumptruck_ds
- this.think_turret = this.turret_atk1;
+ this.think_turret = this.tur_atk1;
// Berserk test from
// http://celephais.net/board/view_thread.php?id=4&start=3465
// -- dumptruck_ds
@@ -1593,25 +977,25 @@ class monster_ogre_marksman: monster_ogre
nonvirtual void() mm_nail1 = [$shoot1, mm_nail2]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
OGRE_DEFAULT_ELEVATION, this.origin, this.enemy.origin);
};
nonvirtual void() mm_nail2 = [$shoot2, mm_nail3]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
this.attack_elevation, this.origin, this.enemy.origin);
};
nonvirtual void() mm_nail3 = [$shoot2, mm_nail4]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
this.attack_elevation, this.origin, this.enemy.origin);
};
nonvirtual void() mm_nail4 = [$shoot3, nail5]
{
ai_face ();
- attack_preach_grenade (this.attack_elevation);
+ fire_grenade (this.origin, 40, 40, this.attack_elevation);
};
// these are for the turret version of monster_ogre_marksman
@@ -1622,25 +1006,25 @@ class monster_ogre_marksman: monster_ogre
nonvirtual void() mm_t_atk1 = [$shoot1, mm_t_atk2]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
OGRE_DEFAULT_ELEVATION, this.origin, this.enemy.origin);
};
nonvirtual void() mm_t_atk2 = [$shoot2, mm_t_atk3]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
this.attack_elevation, this.origin, this.enemy.origin);
};
nonvirtual void() mm_t_atk3 = [$shoot2, mm_t_atk4]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
this.attack_elevation, this.origin, this.enemy.origin);
};
nonvirtual void() mm_t_atk4 = [$shoot3, mm_t_atk5]
{
ai_face ();
- attack_preach_grenade (this.attack_elevation);
+ fire_grenade (this.origin, 40, 40, this.attack_elevation);
};
nonvirtual void() mm_t_atk5 = [$shoot4, mm_t_atk6] { ai_face (); };
nonvirtual void() mm_t_atk6 = [$shoot5, mm_t_atk7] { ai_face (); };
Return to the top of this page or return to the overview of this repo.
Diff qc/monsters/oldone2.qc
diff --git a/qc/monsters/oldone2.qc b/qc/monsters/oldone2.qc
index a2f0b7d..f912547 100644
--- a/qc/monsters/oldone2.qc
+++ b/qc/monsters/oldone2.qc
@@ -34,12 +34,10 @@ class monster_oldone2: base_walkmonster
//--------------------------------------------------------------
nonvirtual void(vector p) shub_missile =
{
- local vector offang;
- local vector org, vec, d;
+ local vector org, d;
local float t;
- offang = vectoangles (this.enemy.origin - this.origin);
- makevectors (offang);
+ makevectors (vectoangles(this.enemy.origin - this.origin));
org = this.origin + p_x * v_forward + p_y * v_right +
p_z * '0 0 1';
@@ -48,49 +46,21 @@ class monster_oldone2: base_walkmonster
if (skill > 1)
{
t = vlen(this.enemy.origin - org) / 300;
- vec = this.enemy.velocity;
- vec_z = 0;
- d = this.enemy.origin + t * vec;
+ d = this.enemy.velocity;
+ d_z = 0;
+ d = this.enemy.origin + t * d;
}
else
{
d = this.enemy.origin;
}
- vec = normalize (d - org);
-
// added this to motivate fireballs dumptruck_ds
- local entity puff;
-
- puff = spawn (base_explosion, origin: org);
+ spawn (base_explosion, origin: org);
// lavaball in your face!
- launch_spike2 (org, vec, 300);
- // dumptruck_ds custom_mdls
- if (this.mdl_proj != "")
- {
- setmodel (newmis, this.mdl_proj);
- }
- else
- {
- setmodel (newmis, "progs/lavaball.mdl");
- }
-
- // dumptruck_ds
- if (!newmis.skin_proj)
- {
- newmis.skin = this.skin_proj;
- }
- else
- {
- newmis.skin = 0;
- }
+ fire_lavaball (org, d - org, LAVABALL_SPEED);
- // setmodel (newmis, "progs/lavaball.mdl");
- newmis.avelocity = '200 100 300';
- setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
- // rocket explosion
- newmis.touch = T_MissileTouch;
sound_attack (this, CHAN_WEAPON, "boss1/throw.wav",
1, ATTN_NORM);
Return to the top of this page or return to the overview of this repo.
Diff qc/monsters/playerclient.qc
diff --git a/qc/monsters/playerclient.qc b/qc/monsters/playerclient.qc
new file mode 100644
index 0000000..df83e32
--- /dev/null
+++ b/qc/monsters/playerclient.qc
@@ -0,0 +1,2571 @@
+//==============================================================================
+// client / player
+//==============================================================================
+
+//======================================================================
+// globals
+//======================================================================
+float modelindex_eyes;
+float modelindex_player;
+
+//======================================================================
+// frame macros
+//======================================================================
+$cd id1/models/player_4
+$origin 0 -6 24
+$base base
+$skin skin
+
+$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
+
+//------------------------------------------------------------------------------
+// Player Class: spawn functions, animation, client handling, etc. -- CEV
+//------------------------------------------------------------------------------
+class player: base_entity
+{
+ float dmgtime;
+
+ //==============================================================
+ // Client Input Handling
+ //==============================================================
+
+ //--------------------------------------------------------------
+ // CheatCommand
+ //--------------------------------------------------------------
+ nonvirtual void() cheat_command =
+ {
+ // 1998-07-29 Cheats coop fix by Maddes start
+ // if (deathmatch || coop)
+ if (deathmatch)
+ // 1998-07-29 Cheats coop fix by Maddes end
+ return;
+
+ this.ammo_cells = 200;
+ this.ammo_nails = 200;
+ this.ammo_rockets = 100;
+ this.ammo_shells = 100;
+ this.items = this.items | IT_AXE | IT_SHOTGUN |
+ IT_SUPER_SHOTGUN | IT_NAILGUN | IT_SUPER_NAILGUN |
+ IT_GRENADE_LAUNCHER | IT_ROCKET_LAUNCHER | IT_LIGHTNING;
+
+ // support for item_key_custom -- iw
+ base_item_key::give_all_keys (this);
+
+ this.weapon = IT_ROCKET_LAUNCHER;
+ this.impulse = 0;
+ this.set_current_ammo ();
+ };
+
+ //--------------------------------------------------------------
+ nonvirtual void() quad_cheat =
+ {
+ // 1998-07-29 Cheats coop fix by Maddes start
+ // if (deathmatch || coop)
+ if (deathmatch)
+ // 1998-07-29 Cheats coop fix by Maddes end
+ return;
+
+ this.super_time = 1;
+ this.super_damage_finished = time + 30;
+ this.items = this.items | IT_QUAD;
+ dprint ("player::quad_cheat: quad damage\n");
+ };
+
+ //--------------------------------------------------------------
+ // ServerflagsCommand -- Just for development
+ //--------------------------------------------------------------
+ nonvirtual void() server_flags_command =
+ {
+ // 1998-07-29 Cheats coop fix by Maddes start
+ if (deathmatch)
+ return;
+ // 1998-07-29 Cheats coop fix by Maddes end
+
+ serverflags = serverflags * 2 + 1;
+ };
+
+ //--------------------------------------------------------------
+ // ChangeWeaponCommand -- was W_ChangeWeapon
+ //--------------------------------------------------------------
+ nonvirtual void() change_weapon =
+ {
+ local float it, haveammo, fl;
+
+ // assign fl to silence a warning -- CEV
+ fl = IT_AXE;
+ it = this.items;
+ haveammo = TRUE;
+
+ switch (this.impulse)
+ {
+ case 1:
+ fl = IT_AXE;
+ break;
+ case 2:
+ fl = IT_SHOTGUN;
+ if (this.ammo_shells < 1)
+ haveammo = FALSE;
+ break;
+ case 3:
+ fl = IT_SUPER_SHOTGUN;
+ if (this.ammo_shells < 2)
+ haveammo = FALSE;
+ break;
+ case 4:
+ fl = IT_NAILGUN;
+ if (this.ammo_nails < 1)
+ haveammo = FALSE;
+ break;
+ case 5:
+ fl = IT_SUPER_NAILGUN;
+ if (this.ammo_nails < 2)
+ haveammo = FALSE;
+ break;
+ case 6:
+ fl = IT_GRENADE_LAUNCHER;
+ if (this.ammo_rockets < 1)
+ haveammo = FALSE;
+ break;
+ case 7:
+ fl = IT_ROCKET_LAUNCHER;
+ if (this.ammo_rockets < 1)
+ haveammo = FALSE;
+ break;
+ case 8:
+ fl = IT_LIGHTNING;
+ if (this.ammo_cells < 1)
+ haveammo = FALSE;
+ break;
+ default:
+ dprint (sprintf("player::change_weapon: WARNING"
+ " bad impulse: %f\n", this.impulse));
+ return;
+ }
+
+ this.impulse = 0;
+
+ if (!(this.items & fl))
+ {
+ // don't have the weapon or the ammo
+ sprint (this, "no weapon.\n");
+ return;
+ }
+
+ if (haveammo == FALSE)
+ {
+ // don't have the ammo
+ sprint (this, "not enough ammo.\n");
+ return;
+ }
+
+ // set weapon, set ammo
+ this.weapon = fl;
+ this.set_current_ammo ();
+ };
+
+ //--------------------------------------------------------------
+ // CycleWeaponCommand -- Go to the next weapon with ammo
+ //--------------------------------------------------------------
+ nonvirtual void() cycle_weapon =
+ {
+ local float haveammo;
+
+ this.impulse = 0;
+
+ while (1)
+ {
+ haveammo = TRUE;
+
+ if (this.weapon == IT_LIGHTNING)
+ {
+ this.weapon = IT_AXE;
+ }
+ else if (this.weapon == IT_AXE)
+ {
+ this.weapon = IT_SHOTGUN;
+ if (this.ammo_shells < 1)
+ haveammo = FALSE;
+ }
+ else if (this.weapon == IT_SHOTGUN)
+ {
+ this.weapon = IT_SUPER_SHOTGUN;
+ if (this.ammo_shells < 2)
+ haveammo = FALSE;
+ }
+ else if (this.weapon == IT_SUPER_SHOTGUN)
+ {
+ this.weapon = IT_NAILGUN;
+ if (this.ammo_nails < 1)
+ haveammo = FALSE;
+ }
+ else if (this.weapon == IT_NAILGUN)
+ {
+ this.weapon = IT_SUPER_NAILGUN;
+ if (this.ammo_nails < 2)
+ haveammo = FALSE;
+ }
+ else if (this.weapon == IT_SUPER_NAILGUN)
+ {
+ this.weapon = IT_GRENADE_LAUNCHER;
+ if (this.ammo_rockets < 1)
+ haveammo = FALSE;
+ }
+ else if (this.weapon == IT_GRENADE_LAUNCHER)
+ {
+ this.weapon = IT_ROCKET_LAUNCHER;
+ if (this.ammo_rockets < 1)
+ haveammo = FALSE;
+ }
+ else if (this.weapon == IT_ROCKET_LAUNCHER)
+ {
+ this.weapon = IT_LIGHTNING;
+ if (this.ammo_cells < 1)
+ haveammo = FALSE;
+ }
+
+ if ((this.items & this.weapon) && haveammo == TRUE)
+ {
+ this.set_current_ammo ();
+ return;
+ }
+ }
+ };
+
+ //--------------------------------------------------------------
+ // CycleWeaponReverseCommand -- Go to the prev weapon with ammo
+ //--------------------------------------------------------------
+ nonvirtual void() cycle_weapon_reverse =
+ {
+ local float haveammo;
+
+ this.impulse = 0;
+
+ while (1)
+ {
+ haveammo = TRUE;
+
+ if (this.weapon == IT_LIGHTNING)
+ {
+ this.weapon = IT_ROCKET_LAUNCHER;
+ if (this.ammo_rockets < 1)
+ haveammo = FALSE;
+ }
+ else if (this.weapon == IT_ROCKET_LAUNCHER)
+ {
+ this.weapon = IT_GRENADE_LAUNCHER;
+ if (this.ammo_rockets < 1)
+ haveammo = FALSE;
+ }
+ else if (this.weapon == IT_GRENADE_LAUNCHER)
+ {
+ this.weapon = IT_SUPER_NAILGUN;
+ if (this.ammo_nails < 2)
+ haveammo = FALSE;
+ }
+ else if (this.weapon == IT_SUPER_NAILGUN)
+ {
+ this.weapon = IT_NAILGUN;
+ if (this.ammo_nails < 1)
+ haveammo = FALSE;
+ }
+ else if (this.weapon == IT_NAILGUN)
+ {
+ this.weapon = IT_SUPER_SHOTGUN;
+ if (this.ammo_shells < 2)
+ haveammo = FALSE;
+ }
+ else if (this.weapon == IT_SUPER_SHOTGUN)
+ {
+ this.weapon = IT_SHOTGUN;
+ if (this.ammo_shells < 1)
+ haveammo = FALSE;
+ }
+ else if (this.weapon == IT_SHOTGUN)
+ {
+ this.weapon = IT_AXE;
+ }
+ else if (this.weapon == IT_AXE)
+ {
+ this.weapon = IT_LIGHTNING;
+ if (this.ammo_cells < 1)
+ haveammo = FALSE;
+ }
+
+ if ((this.items & this.weapon) && haveammo == TRUE)
+ {
+ this.set_current_ammo ();
+ return;
+ }
+ }
+ };
+
+ //--------------------------------------------------------------
+ // ImpulseCommands
+ //--------------------------------------------------------------
+ nonvirtual void() impulse_commands =
+ {
+ switch (this.impulse)
+ {
+ case 1..8:
+ this.change_weapon ();
+ return;
+ case 9:
+ this.cheat_command ();
+ break;
+ case 10:
+ this.cycle_weapon ();
+ break;
+ case 11:
+ this.server_flags_command ();
+ break;
+ case 12:
+ this.cycle_weapon_reverse ();
+ break;
+ case 100:
+ // dumptruck_ds version inspired by Copper
+ sprint (this, version);
+ break;
+ case 255:
+ this.quad_cheat ();
+ break;
+ default:
+ dprint (sprintf("player::impulse_commands: "
+ "unknown impulse %g\n", this.impulse));
+ break;
+ }
+
+ this.impulse = 0;
+ };
+
+ //==============================================================
+ // Client & Player Sounds
+ //==============================================================
+
+ //--------------------------------------------------------------
+ // SuperDamageSound -- Plays sound if needed
+ //--------------------------------------------------------------
+ nonvirtual void() superdamage_sound =
+ {
+ if (super_damage_finished > time && super_sound < time)
+ {
+ this.super_sound = time + 1;
+ sound (this, CHAN_AUTO, "items/damage3.wav",
+ 1, ATTN_NORM);
+ }
+ };
+
+ //==============================================================
+ // Ammo Handling, Weapon Switching, Attack
+ //==============================================================
+
+ //--------------------------------------------------------------
+ // set_current_ammo -- was W_SetCurrentAmmo in weapons.qc
+ //--------------------------------------------------------------
+ nonvirtual void() set_current_ammo =
+ {
+ // get out of any weapon firing states
+ this.run1 ();
+
+ this.items = this.items - (this.items & (IT_SHELLS | IT_NAILS |
+ IT_ROCKETS | IT_CELLS));
+
+ if (this.weapon == IT_AXE)
+ {
+ this.currentammo = 0;
+ this.weaponmodel = "progs/v_axe.mdl";
+ this.weaponframe = 0;
+ }
+ else if (this.weapon == IT_SHOTGUN)
+ {
+ this.currentammo = this.ammo_shells;
+ this.weaponmodel = "progs/v_shot.mdl";
+ this.weaponframe = 0;
+ this.items = this.items | IT_SHELLS;
+ }
+ else if (this.weapon == IT_SUPER_SHOTGUN)
+ {
+ this.currentammo = this.ammo_shells;
+ this.weaponmodel = "progs/v_shot2.mdl";
+ this.weaponframe = 0;
+ this.items = this.items | IT_SHELLS;
+ }
+ else if (this.weapon == IT_NAILGUN)
+ {
+ this.currentammo = this.ammo_nails;
+ this.weaponmodel = "progs/v_nail.mdl";
+ this.weaponframe = 0;
+ this.items = this.items | IT_NAILS;
+ }
+ else if (this.weapon == IT_SUPER_NAILGUN)
+ {
+ this.currentammo = this.ammo_nails;
+ this.weaponmodel = "progs/v_nail2.mdl";
+ this.weaponframe = 0;
+ this.items = this.items | IT_NAILS;
+ }
+ else if (this.weapon == IT_GRENADE_LAUNCHER)
+ {
+ this.currentammo = this.ammo_rockets;
+ this.weaponmodel = "progs/v_rock.mdl";
+ this.weaponframe = 0;
+ this.items = this.items | IT_ROCKETS;
+ }
+ else if (this.weapon == IT_ROCKET_LAUNCHER)
+ {
+ this.currentammo = this.ammo_rockets;
+ this.weaponmodel = "progs/v_rock2.mdl";
+ this.weaponframe = 0;
+ this.items = this.items | IT_ROCKETS;
+ }
+ else if (this.weapon == IT_LIGHTNING)
+ {
+ this.currentammo = this.ammo_cells;
+ this.weaponmodel = "progs/v_light.mdl";
+ this.weaponframe = 0;
+ this.items = this.items | IT_CELLS;
+ }
+ else
+ {
+ this.currentammo = 0;
+ this.weaponmodel = "";
+ this.weaponframe = 0;
+ }
+ };
+
+ //--------------------------------------------------------------
+ // best_weapon -- was W_BestWeapon in weapons.qc
+ //--------------------------------------------------------------
+ nonvirtual float() best_weapon =
+ {
+ if (this.waterlevel <= WATERLEVEL_FEET &&
+ this.ammo_cells >= 1 && (this.items & IT_LIGHTNING))
+ {
+ return IT_LIGHTNING;
+ }
+
+ if (this.ammo_nails >= 2 && (this.items & IT_SUPER_NAILGUN))
+ return IT_SUPER_NAILGUN;
+
+ if (this.ammo_shells >= 2 && (this.items & IT_SUPER_SHOTGUN))
+ return IT_SUPER_SHOTGUN;
+
+ if (this.ammo_nails >= 1 && (this.items & IT_NAILGUN))
+ return IT_NAILGUN;
+
+ if (this.ammo_shells >= 1 && (this.items & IT_SHOTGUN))
+ return IT_SHOTGUN;
+
+ return IT_AXE;
+ };
+
+ //--------------------------------------------------------------
+ nonvirtual float() check_no_ammo =
+ {
+ if (this.currentammo > 0)
+ return TRUE;
+
+ if (this.weapon == IT_AXE)
+ return TRUE;
+
+ this.weapon = this.best_weapon ();
+ this.set_current_ammo ();
+
+ // drop the weapon down
+ return FALSE;
+ };
+
+ //--------------------------------------------------------------
+ // Weapon 1: W_FireAxe
+ //--------------------------------------------------------------
+ nonvirtual void() fire_axe =
+ {
+ local vector source;
+ local vector org;
+
+ makevectors (this.v_angle);
+ source = this.origin + '0 0 16';
+ traceline (source, source + v_forward * 64, FALSE, this);
+ if (trace_fraction == 1.0)
+ return;
+ org = trace_endpos - v_forward * 4;
+
+ if (trace_ent.takedamage)
+ {
+ trace_ent.axhitme = 1;
+ SpawnBlood (org, '0 0 0', 20);
+ t_damage2 (trace_ent, this, this, 20);
+ }
+ else
+ {
+ // hit wall
+ sound (this, 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);
+ }
+ };
+
+ //--------------------------------------------------------------
+ // Weapon 2: W_FireShotgun
+ //--------------------------------------------------------------
+ nonvirtual void() fire_shotgun =
+ {
+ local vector dir;
+
+ sound (this, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);
+
+ this.punchangle_x = -2;
+
+ this.currentammo = this.ammo_shells = this.ammo_shells - 1;
+ dir = aim (this, 100000);
+ // TODO CEV
+ FireBullets (6, dir, '0.04 0.04 0');
+ };
+
+ //--------------------------------------------------------------
+ // Weapon 3: W_FireSuperShotgun
+ //--------------------------------------------------------------
+ nonvirtual void() fire_supershotgun =
+ {
+ local vector dir;
+
+ if (this.currentammo == 1)
+ {
+ this.fire_shotgun ();
+ return;
+ }
+
+ sound (this, CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);
+
+ this.punchangle_x = -4;
+
+ this.currentammo = this.ammo_shells = this.ammo_shells - 2;
+ dir = aim (this, 100000);
+ FireBullets (14, dir, '0.14 0.08 0');
+ };
+
+ //--------------------------------------------------------------
+ // Weapon 4: W_FireSpikes
+ //--------------------------------------------------------------
+ nonvirtual void(float offset) fire_spikes =
+ {
+ local vector dir;
+
+ makevectors (this.v_angle);
+
+ if (this.ammo_nails >= 2 && this.weapon == IT_SUPER_NAILGUN)
+ {
+ fire_superspikes ();
+ return;
+ }
+
+ if (this.ammo_nails < 1)
+ {
+ this.weapon = this.best_weapon ();
+ this.set_current_ammo ();
+ return;
+ }
+
+ sound (this, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
+ this.attack_finished = time + 0.2;
+ this.currentammo = this.ammo_nails = this.ammo_nails - 1;
+
+ dir = aim (this, SPIKE_SPEED);
+ // dir = normalize (dir);
+ // SetSpeed
+ dir *= min (SPIKE_SPEED, frame_maxvelocity);
+
+ spawn (projectile_spike,
+ owner: this,
+ // seven Nailgun position fix - thanks to Greenwood
+ // -- dumptruck_ds
+ origin: this.origin + this.view_ofs + v_up * -8 +
+ v_right * (offset * 0.5),
+ velocity: dir,
+ direct_damage: SPIKE_NORMAL_DAMAGE);
+
+ this.punchangle_x = -2;
+ };
+
+ //--------------------------------------------------------------
+ // Weapon 5: W_FireSuperSpikes
+ //--------------------------------------------------------------
+ nonvirtual void() fire_superspikes =
+ {
+ local vector dir;
+
+ sound (this, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
+ this.attack_finished = time + 0.2;
+ this.currentammo = this.ammo_nails = this.ammo_nails - 2;
+
+ dir = aim (this, SPIKE_SPEED);
+ // dir = normalize (dir);
+ // SetSpeed
+ dir *= min (SPIKE_SPEED, frame_maxvelocity);
+
+ spawn (projectile_spike,
+ owner: this,
+ // seven Nailgun position fix - thanks to Greenwood
+ // -- dumptruck_ds
+ origin: this.origin + '0 0 16',
+ velocity: dir,
+ direct_damage: SPIKE_SUPER_DAMAGE);
+
+ this.punchangle_x = -2;
+ };
+
+ //--------------------------------------------------------------
+ // Weapon 6: W_FireGrenade
+ //--------------------------------------------------------------
+ nonvirtual void() fire_grenade =
+ {
+ local vector missile_velocity = '0 0 0';
+
+ this.currentammo = this.ammo_rockets = this.ammo_rockets - 1;
+
+ sound (this, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
+
+ this.punchangle_x = -2;
+
+ // set missile speed
+ makevectors (this.v_angle);
+
+ if (this.v_angle_x)
+ {
+ missile_velocity = v_forward * GRENADE_SPEED +
+ v_up * 200 + crandom() * v_right * 10 +
+ crandom() * v_up * 10;
+ }
+ else
+ {
+ missile_velocity = aim (this, 10000);
+ missile_velocity = missile_velocity * GRENADE_SPEED;
+ missile_velocity_z = 200;
+ }
+
+ spawn (projectile_grenade,
+ owner: this,
+ origin: this.origin,
+ velocity: missile_velocity);
+ };
+
+ //--------------------------------------------------------------
+ // Weapon 7: W_FireRocket
+ //--------------------------------------------------------------
+ nonvirtual void() fire_rocket =
+ {
+ local vector missile_velocity = '0 0 0';
+
+ this.currentammo = this.ammo_rockets = this.ammo_rockets - 1;
+
+ sound (this, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
+
+ this.punchangle_x = -2;
+
+ // set missile speed
+ makevectors (this.v_angle);
+ missile_velocity = aim (this, 1000);
+ missile_velocity *= ROCKET_SPEED;
+
+ spawn (projectile_rocket,
+ owner: this,
+ origin: this.origin + v_forward * 8 + '0 0 16',
+ velocity: missile_velocity,
+ angles: vectoangles (missile_velocity));
+ };
+
+ //--------------------------------------------------------------
+ // Weapon 8: W_FireLightning
+ //--------------------------------------------------------------
+ nonvirtual void() fire_lightning =
+ {
+ if (this.ammo_cells < 1)
+ {
+ this.weapon = this.best_weapon ();
+ this.set_current_ammo ();
+ return;
+ }
+
+ // explode if under water
+ if (this.waterlevel > WATERLEVEL_FEET)
+ {
+ local float cells = this.ammo_cells;
+ this.ammo_cells = 0;
+ this.set_current_ammo ();
+ this.t_radiusdamage2 (this, this, 35 * cells, world);
+ return;
+ }
+
+ if (this.t_width < time)
+ {
+ sound (this, CHAN_WEAPON, "weapons/lhit.wav",
+ 1, ATTN_NORM);
+ this.t_width = time + 0.6;
+ }
+ this.punchangle_x = -2;
+
+ this.currentammo = this.ammo_cells = this.ammo_cells - 1;
+
+ // TODO CEV
+ // local vector org = this.origin;
+ local vector org = this.origin + '0 0 16';
+ makevectors (this.v_angle);
+
+ traceline (org, org + v_forward * 600, TRUE, this);
+
+ WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
+ WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
+ WriteEntity (MSG_BROADCAST, this);
+ WriteCoord (MSG_BROADCAST, org_x);
+ WriteCoord (MSG_BROADCAST, org_y);
+ WriteCoord (MSG_BROADCAST, org_z);
+ WriteCoord (MSG_BROADCAST, trace_endpos_x);
+ WriteCoord (MSG_BROADCAST, trace_endpos_y);
+ WriteCoord (MSG_BROADCAST, trace_endpos_z);
+
+ weapon_lightning::lightning_damage (this.origin,
+ trace_endpos + v_forward * 4, this, 30);
+ };
+
+ //--------------------------------------------------------------
+ // PlayerAttack -- An attack impulse can be triggered now
+ //--------------------------------------------------------------
+ nonvirtual void() attack =
+ {
+ local float r;
+
+ if (!this.check_no_ammo())
+ return;
+
+ // calculate forward angle for velocity
+ makevectors (this.v_angle);
+ // wake monsters up
+ this.show_hostile = time + 1;
+
+ if (this.weapon == IT_AXE)
+ {
+ sound (this, CHAN_WEAPON, "weapons/ax1.wav",
+ 1, ATTN_NORM);
+ r = random ();
+ if (r < 0.25)
+ this.axe1 ();
+ else if (r < 0.5)
+ this.axeb1 ();
+ else if (r < 0.75)
+ this.axec1 ();
+ else
+ this.axed1 ();
+ this.attack_finished = time + 0.5;
+ }
+ else if (this.weapon == IT_SHOTGUN)
+ {
+ this.shot1 ();
+ this.fire_shotgun ();
+ this.attack_finished = time + 0.5;
+ }
+ else if (this.weapon == IT_SUPER_SHOTGUN)
+ {
+ this.shot1 ();
+ this.fire_supershotgun ();
+ this.attack_finished = time + 0.7;
+ }
+ else if (this.weapon == IT_NAILGUN)
+ {
+ this.nail1 ();
+ }
+ else if (this.weapon == IT_SUPER_NAILGUN)
+ {
+ this.nail1 ();
+ }
+ else if (this.weapon == IT_GRENADE_LAUNCHER)
+ {
+ this.rocket1 ();
+ this.fire_grenade ();
+ this.attack_finished = time + 0.6;
+ }
+ else if (this.weapon == IT_ROCKET_LAUNCHER)
+ {
+ this.rocket1 ();
+ this.fire_rocket ();
+ this.attack_finished = time + 0.8;
+ }
+ else if (this.weapon == IT_LIGHTNING)
+ {
+ this.light1 ();
+ this.attack_finished = time + 0.1;
+ sound (this, CHAN_AUTO, "weapons/lstart.wav",
+ 1, ATTN_NORM);
+ }
+ };
+
+ //==============================================================
+ // Pain and Death
+ //==============================================================
+
+ //--------------------------------------------------------------
+ nonvirtual void() set_suicide_frame =
+ {
+ // used by klill command and disconnect command
+ if (this.model != "progs/player.mdl")
+ // allready gibbed
+ return;
+ this.frame = $deatha11;
+ this.solid = SOLID_NOT;
+ this.movetype = MOVETYPE_TOSS;
+ this.deadflag = DEAD_DEAD;
+ this.nextthink = -1;
+ };
+
+ //--------------------------------------------------------------
+ // PainSound
+ //--------------------------------------------------------------
+ nonvirtual void() pain_sound =
+ {
+ local float rs;
+
+ if (this.health < 0)
+ return;
+
+ if (damage_attacker.classname == "teledeath")
+ {
+ sound (this, CHAN_VOICE, "player/teledth1.wav",
+ 1, ATTN_NONE);
+ return;
+ }
+
+ // water pain sounds
+ if (this.watertype == CONTENT_WATER &&
+ this.waterlevel == WATERLEVEL_EYES)
+ {
+ PlayerDeathBubbles (1);
+ if (random() > 0.5)
+ sound (this, CHAN_VOICE, "player/drown1.wav",
+ 1, ATTN_NORM);
+ else
+ sound (this, CHAN_VOICE, "player/drown2.wav",
+ 1, ATTN_NORM);
+ return;
+ }
+
+ // slime pain sounds
+ if (this.watertype == CONTENT_SLIME)
+ {
+ // FIX ME put in some steam here
+ // 1998-08-10 Player gulps bubbles when hurt in slime
+ // by Maddes start
+ if (this.waterlevel == WATERLEVEL_EYES)
+ PlayerDeathBubbles (1);
+ // 1998-08-10 Player gulps bubbles when hurt in slime
+ // by Maddes end
+ if (random() > 0.5)
+ sound (this, CHAN_VOICE, "player/lburn1.wav",
+ 1, ATTN_NORM);
+ else
+ sound (this, CHAN_VOICE, "player/lburn2.wav",
+ 1, ATTN_NORM);
+ return;
+ }
+
+ if (this.watertype == CONTENT_LAVA)
+ {
+ if (random() > 0.5)
+ sound (this, CHAN_VOICE, "player/lburn1.wav",
+ 1, ATTN_NORM);
+ else
+ sound (this, CHAN_VOICE, "player/lburn2.wav",
+ 1, ATTN_NORM);
+ return;
+ }
+
+ if (this.pain_finished > time)
+ {
+ this.axhitme = 0;
+ return;
+ }
+
+ // don't make multiple pain sounds right after each other
+ this.pain_finished = time + 0.5;
+
+ // ax pain sound
+ if (this.axhitme == 1)
+ {
+ this.axhitme = 0;
+ sound (this, CHAN_VOICE, "player/axhit1.wav",
+ 1, ATTN_NORM);
+ return;
+ }
+
+ rs = rint ((random() * 5) + 1);
+
+ this.noise = "";
+ if (rs == 1)
+ this.noise = "player/pain1.wav";
+ else if (rs == 2)
+ this.noise = "player/pain2.wav";
+ else if (rs == 3)
+ this.noise = "player/pain3.wav";
+ else if (rs == 4)
+ this.noise = "player/pain4.wav";
+ else if (rs == 5)
+ this.noise = "player/pain5.wav";
+ else
+ this.noise = "player/pain6.wav";
+
+ sound (this, CHAN_VOICE, this.noise, 1, ATTN_NORM);
+ return;
+ };
+
+ //--------------------------------------------------------------
+ // PlayerDeathSound
+ //--------------------------------------------------------------
+ nonvirtual void() death_sound =
+ {
+ local float rs;
+
+ // water death sounds
+ if (this.waterlevel == WATERLEVEL_EYES)
+ {
+ PlayerDeathBubbles (20);
+ sound (this, CHAN_VOICE, "player/h2odeath.wav",
+ 1, ATTN_NONE);
+ return;
+ }
+
+ rs = rint ((random() * 4) + 1);
+ if (rs == 1)
+ this.noise = "player/death1.wav";
+ else if (rs == 2)
+ this.noise = "player/death2.wav";
+ else if (rs == 3)
+ this.noise = "player/death3.wav";
+ else if (rs == 4)
+ this.noise = "player/death4.wav";
+ else if (rs == 5)
+ this.noise = "player/death5.wav";
+
+ sound (this, CHAN_VOICE, this.noise, 1, ATTN_NONE);
+ return;
+ };
+
+ //--------------------------------------------------------------
+ // PlayerDead -- the player is dead, hold them there
+ //--------------------------------------------------------------
+ nonvirtual void() dead =
+ {
+ this.nextthink = -1;
+ // allow respawn after a certain time
+ this.deadflag = DEAD_DEAD;
+ };
+
+ //==============================================================
+ // Player Think Functions
+ //==============================================================
+
+ //--------------------------------------------------------------
+ // Player Stand function
+ //--------------------------------------------------------------
+ nonvirtual void() stand1 = [$axstnd1, stand1]
+ {
+ this.weaponframe = 0;
+ if (this.velocity_x || this.velocity_y)
+ {
+ this.walkframe = 0;
+ this.run1 ();
+ return;
+ }
+
+ if (this.weapon == IT_AXE)
+ {
+ if (this.walkframe >= 12)
+ this.walkframe = 0;
+ this.frame = $axstnd1 + this.walkframe;
+ }
+ else
+ {
+ if (this.walkframe >= 5)
+ this.walkframe = 0;
+ this.frame = $stand1 + this.walkframe;
+ }
+ this.walkframe = this.walkframe + 1;
+ };
+
+ //--------------------------------------------------------------
+ // Player Run function
+ //--------------------------------------------------------------
+ nonvirtual void() run1 = [$rockrun1, run1]
+ {
+ this.weaponframe = 0;
+ if (!this.velocity_x && !this.velocity_y)
+ {
+ this.walkframe = 0;
+ this.stand1 ();
+ return;
+ }
+
+ if (this.weapon == IT_AXE)
+ {
+ if (this.walkframe == 6)
+ this.walkframe = 0;
+ this.frame = $axrun1 + this.walkframe;
+ }
+ else
+ {
+ if (this.walkframe == 6)
+ this.walkframe = 0;
+ this.frame = this.frame + this.walkframe;
+ }
+ this.walkframe = this.walkframe + 1;
+ };
+
+ //--------------------------------------------------------------
+ // Player Projectile Attack
+ //--------------------------------------------------------------
+ nonvirtual void() shot1 = [$shotatt1, shot2]
+ {
+ this.weaponframe = 1;
+ this.effects = this.effects | EF_MUZZLEFLASH;
+ };
+ nonvirtual void() shot2 = [$shotatt2, shot3] { this.weaponframe = 2; };
+ nonvirtual void() shot3 = [$shotatt3, shot4] { this.weaponframe = 3; };
+ nonvirtual void() shot4 = [$shotatt4, shot5] { this.weaponframe = 4; };
+ nonvirtual void() shot5 = [$shotatt5, shot6] { this.weaponframe = 5; };
+ nonvirtual void() shot6 = [$shotatt6, run1] { this.weaponframe = 6; };
+
+ //--------------------------------------------------------------
+ // Player Axe Attack A
+ //--------------------------------------------------------------
+ nonvirtual void() axe1 = [$axatt1, axe2] { this.weaponframe = 1; };
+ nonvirtual void() axe2 = [$axatt2, axe3] { this.weaponframe = 2; };
+ nonvirtual void() axe3 = [$axatt3, axe4]
+ {
+ this.weaponframe = 3;
+ this.fire_axe ();
+ };
+ nonvirtual void() axe4 = [$axatt4, run1] { this.weaponframe = 4; };
+
+ //--------------------------------------------------------------
+ // Player Axe Attack B
+ //--------------------------------------------------------------
+ nonvirtual void() axeb1 = [$axattb1, axeb2] { this.weaponframe = 5; };
+ nonvirtual void() axeb2 = [$axattb2, axeb3] { this.weaponframe = 6; };
+ nonvirtual void() axeb3 = [$axattb3, axeb4]
+ {
+ this.weaponframe = 7;
+ this.fire_axe ();
+ };
+ nonvirtual void() axeb4 = [$axattb4, run1] { this.weaponframe = 8; };
+
+ //--------------------------------------------------------------
+ // Player Axe Attack C
+ //--------------------------------------------------------------
+ nonvirtual void() axec1 = [$axattc1, axec2] { this.weaponframe = 1; };
+ nonvirtual void() axec2 = [$axattc2, axec3] { this.weaponframe = 2; };
+ nonvirtual void() axec3 = [$axattc3, axec4]
+ {
+ this.weaponframe = 3;
+ this.fire_axe ();
+ };
+ nonvirtual void() axec4 = [$axattc4, run1] { this.weaponframe = 4; };
+
+ //--------------------------------------------------------------
+ // Player Axe Attack D
+ //--------------------------------------------------------------
+ nonvirtual void() axed1 = [$axattd1, axed2] { this.weaponframe = 5; };
+ nonvirtual void() axed2 = [$axattd2, axed3] { this.weaponframe = 6; };
+ nonvirtual void() axed3 = [$axattd3, axed4]
+ {
+ this.weaponframe = 7;
+ this.fire_axe ();
+ };
+ nonvirtual void() axed4 = [$axattd4, run1] { this.weaponframe = 8; };
+
+ //--------------------------------------------------------------
+ // Player Nail Attack
+ //--------------------------------------------------------------
+ nonvirtual void() nail1 = [$nailatt1, nail2]
+ {
+ this.effects = this.effects | EF_MUZZLEFLASH;
+
+ if (!this.button0)
+ {
+ this.run1 ();
+ return;
+ }
+
+ this.weaponframe = this.weaponframe + 1;
+ if (this.weaponframe == 9)
+ this.weaponframe = 1;
+ this.superdamage_sound ();
+ this.fire_spikes (4);
+ this.attack_finished = time + 0.2;
+ };
+ nonvirtual void() nail2 = [$nailatt2, nail1]
+ {
+ this.effects = this.effects | EF_MUZZLEFLASH;
+
+ if (!this.button0)
+ {
+ this.run1 ();
+ return;
+ }
+
+ this.weaponframe = this.weaponframe + 1;
+ if (this.weaponframe == 9)
+ this.weaponframe = 1;
+ this.superdamage_sound ();
+ this.fire_spikes (-4);
+ this.attack_finished = time + 0.2;
+ };
+
+ //--------------------------------------------------------------
+ // Player LG Attack
+ //--------------------------------------------------------------
+ nonvirtual void() light1 = [$light1, light2]
+ {
+ this.effects = this.effects | EF_MUZZLEFLASH;
+
+ if (!this.button0)
+ {
+ this.run1 ();
+ return;
+ }
+
+ this.weaponframe = this.weaponframe + 1;
+ if (this.weaponframe == 5)
+ this.weaponframe = 1;
+ this.superdamage_sound ();
+ this.fire_lightning ();
+ this.attack_finished = time + 0.2;
+ };
+ nonvirtual void() light2 = [$light2, light1]
+ {
+ this.effects = this.effects | EF_MUZZLEFLASH;
+
+ if (!this.button0)
+ {
+ this.run1 ();
+ return;
+ }
+
+ this.weaponframe = this.weaponframe + 1;
+ if (this.weaponframe == 5)
+ this.weaponframe = 1;
+ this.superdamage_sound ();
+ this.fire_lightning ();
+ this.attack_finished = time + 0.2;
+ };
+
+ //--------------------------------------------------------------
+ // Player Rocket Attack
+ //--------------------------------------------------------------
+ nonvirtual void() rocket1 = [$rockatt1, rocket2]
+ {
+ this.weaponframe = 1;
+ this.effects = this.effects | EF_MUZZLEFLASH;
+ };
+ nonvirtual void() rocket2 = [$rockatt2, rocket3] { weaponframe = 2; };
+ nonvirtual void() rocket3 = [$rockatt3, rocket4] { weaponframe = 3; };
+ nonvirtual void() rocket4 = [$rockatt4, rocket5] { weaponframe = 4; };
+ nonvirtual void() rocket5 = [$rockatt5, rocket6] { weaponframe = 5; };
+ nonvirtual void() rocket6 = [$rockatt6, run1] { weaponframe = 6; };
+
+ //--------------------------------------------------------------
+ // Player Pain state A
+ //--------------------------------------------------------------
+ nonvirtual void() pain1 = [$pain1, pain2]
+ {
+ this.pain_sound ();
+ this.weaponframe = 0;
+ };
+ nonvirtual void() pain2 = [$pain2, pain3] { };
+ nonvirtual void() pain3 = [$pain3, pain4] { };
+ nonvirtual void() pain4 = [$pain4, pain5] { };
+ nonvirtual void() pain5 = [$pain5, pain6] { };
+ nonvirtual void() pain6 = [$pain6, run1] { };
+
+ //--------------------------------------------------------------
+ // Player Axe Pain state A
+ //--------------------------------------------------------------
+ nonvirtual void() axpain1 = [$axpain1, axpain2]
+ {
+ this.pain_sound ();
+ this.weaponframe = 0;
+ };
+ nonvirtual void() axpain2 = [$axpain2, axpain3] {};
+ nonvirtual void() axpain3 = [$axpain3, axpain4] {};
+ nonvirtual void() axpain4 = [$axpain4, axpain5] {};
+ nonvirtual void() axpain5 = [$axpain5, axpain6] {};
+ nonvirtual void() axpain6 = [$axpain6, run1] {};
+
+ //--------------------------------------------------------------
+ // Player Death state A
+ //--------------------------------------------------------------
+ nonvirtual void() diea1 = [$deatha1, diea2] {};
+ nonvirtual void() diea2 = [$deatha2, diea3] {};
+ nonvirtual void() diea3 = [$deatha3, diea4] {};
+ nonvirtual void() diea4 = [$deatha4, diea5] {};
+ nonvirtual void() diea5 = [$deatha5, diea6] {};
+ nonvirtual void() diea6 = [$deatha6, diea7] {};
+ nonvirtual void() diea7 = [$deatha7, diea8] {};
+ nonvirtual void() diea8 = [$deatha8, diea9] {};
+ nonvirtual void() diea9 = [$deatha9, diea10] {};
+ nonvirtual void() diea10 = [$deatha10, diea11] {};
+ nonvirtual void() diea11 = [$deatha11, diea11] { this.dead (); };
+
+ //--------------------------------------------------------------
+ // Player Death state B
+ //--------------------------------------------------------------
+ nonvirtual void() dieb1 = [$deathb1, dieb2] {};
+ nonvirtual void() dieb2 = [$deathb2, dieb3] {};
+ nonvirtual void() dieb3 = [$deathb3, dieb4] {};
+ nonvirtual void() dieb4 = [$deathb4, dieb5] {};
+ nonvirtual void() dieb5 = [$deathb5, dieb6] {};
+ nonvirtual void() dieb6 = [$deathb6, dieb7] {};
+ nonvirtual void() dieb7 = [$deathb7, dieb8] {};
+ nonvirtual void() dieb8 = [$deathb8, dieb9] {};
+ nonvirtual void() dieb9 = [$deathb9, dieb9] { this.dead (); };
+
+ //--------------------------------------------------------------
+ // Player Death state C
+ //--------------------------------------------------------------
+ nonvirtual void() diec1 = [$deathc1, diec2] {};
+ nonvirtual void() diec2 = [$deathc2, diec3] {};
+ nonvirtual void() diec3 = [$deathc3, diec4] {};
+ nonvirtual void() diec4 = [$deathc4, diec5] {};
+ nonvirtual void() diec5 = [$deathc5, diec6] {};
+ nonvirtual void() diec6 = [$deathc6, diec7] {};
+ nonvirtual void() diec7 = [$deathc7, diec8] {};
+ nonvirtual void() diec8 = [$deathc8, diec9] {};
+ nonvirtual void() diec9 = [$deathc9, diec10] {};
+ nonvirtual void() diec10 = [$deathc10, diec11] {};
+ nonvirtual void() diec11 = [$deathc11, diec12] {};
+ nonvirtual void() diec12 = [$deathc12, diec13] {};
+ nonvirtual void() diec13 = [$deathc13, diec14] {};
+ nonvirtual void() diec14 = [$deathc14, diec15] {};
+ nonvirtual void() diec15 = [$deathc15, diec15] { this.dead (); };
+
+ //--------------------------------------------------------------
+ // Player Death state D
+ //--------------------------------------------------------------
+ nonvirtual void() died1 = [$deathd1, died2] {};
+ nonvirtual void() died2 = [$deathd2, died3] {};
+ nonvirtual void() died3 = [$deathd3, died4] {};
+ nonvirtual void() died4 = [$deathd4, died5] {};
+ nonvirtual void() died5 = [$deathd5, died6] {};
+ nonvirtual void() died6 = [$deathd6, died7] {};
+ nonvirtual void() died7 = [$deathd7, died8] {};
+ nonvirtual void() died8 = [$deathd8, died9] {};
+ nonvirtual void() died9 = [$deathd9, died9] { this.dead (); };
+
+ //--------------------------------------------------------------
+ // Player Death state E
+ //--------------------------------------------------------------
+ nonvirtual void() diee1 = [$deathe1, diee2] {};
+ nonvirtual void() diee2 = [$deathe2, diee3] {};
+ nonvirtual void() diee3 = [$deathe3, diee4] {};
+ nonvirtual void() diee4 = [$deathe4, diee5] {};
+ nonvirtual void() diee5 = [$deathe5, diee6] {};
+ nonvirtual void() diee6 = [$deathe6, diee7] {};
+ nonvirtual void() diee7 = [$deathe7, diee8] {};
+ nonvirtual void() diee8 = [$deathe8, diee9] {};
+ nonvirtual void() diee9 = [$deathe9, diee9] { this.dead (); };
+
+ //--------------------------------------------------------------
+ // Player Axe Death state A
+ //--------------------------------------------------------------
+ nonvirtual void() die_ax1 = [$axdeth1, die_ax2] {};
+ nonvirtual void() die_ax2 = [$axdeth2, die_ax3] {};
+ nonvirtual void() die_ax3 = [$axdeth3, die_ax4] {};
+ nonvirtual void() die_ax4 = [$axdeth4, die_ax5] {};
+ nonvirtual void() die_ax5 = [$axdeth5, die_ax6] {};
+ nonvirtual void() die_ax6 = [$axdeth6, die_ax7] {};
+ nonvirtual void() die_ax7 = [$axdeth7, die_ax8] {};
+ nonvirtual void() die_ax8 = [$axdeth8, die_ax9] {};
+ nonvirtual void() die_ax9 = [$axdeth9, die_ax9] { this.dead (); };
+
+ //--------------------------------------------------------------
+ // PlayerDeathThink -- called from prethink when dead
+ //--------------------------------------------------------------
+ nonvirtual void() think_death =
+ {
+ local float forward;
+
+ if ((this.flags & FL_ONGROUND))
+ {
+ forward = vlen (this.velocity);
+ forward = forward - 20;
+ if (forward <= 0)
+ this.velocity = '0 0 0';
+ else
+ this.velocity = forward *
+ normalize (this.velocity);
+ }
+
+ // wait for all buttons released
+ if (this.deadflag == DEAD_DEAD)
+ {
+ if (this.button2 || this.button1 || this.button0)
+ return;
+ this.deadflag = DEAD_RESPAWNABLE;
+ return;
+ }
+
+ // wait for any button down
+ if (!this.button2 && !this.button1 && !this.button0)
+ return;
+
+ this.button0 = 0;
+ this.button1 = 0;
+ this.button2 = 0;
+ this.init_respawn ();
+ };
+
+ //--------------------------------------------------------------
+ // WaterMove
+ //--------------------------------------------------------------
+ nonvirtual void() prethink_watermove =
+ {
+ if (this.movetype == MOVETYPE_NOCLIP)
+ {
+ this.air_finished = time + 120;
+ return;
+ }
+
+ if (this.health < 0)
+ return;
+
+ if (this.waterlevel != 3)
+ {
+ if (this.air_finished < time)
+ sound (this, CHAN_VOICE, "player/gasp2.wav",
+ 1, ATTN_NORM);
+ else if (this.air_finished < time + 9)
+ sound (this, CHAN_VOICE, "player/gasp1.wav",
+ 1, ATTN_NORM);
+ this.air_finished = time + 12;
+ this.dmg = 2;
+ }
+ else if (this.air_finished < time)
+ {
+ // drown!
+ if (this.pain_finished < time)
+ {
+ this.dmg = this.dmg + 2;
+ if (this.dmg > 15)
+ this.dmg = 10;
+ this.deathtype = "drowning";
+ this.t_damage2 (this, world, world, this.dmg);
+ this.deathtype = "";
+ this.pain_finished = time + 1;
+ }
+ }
+
+ if (!this.waterlevel)
+ {
+ if (this.flags & FL_INWATER)
+ {
+ // play leave water sound
+ sound (this, CHAN_BODY, "misc/outwater.wav",
+ 1, ATTN_NORM);
+ this.flags = this.flags - FL_INWATER;
+ }
+ return;
+ }
+
+ if (this.watertype == CONTENT_LAVA)
+ {
+ // do damage
+ if (this.dmgtime < time)
+ {
+ if (this.radsuit_finished > time)
+ this.dmgtime = time + 1;
+ else
+ this.dmgtime = time + 0.2;
+
+ this.deathtype = "lava";
+ this.t_damage2 (this, world, world,
+ 10 * this.waterlevel);
+ this.deathtype = "";
+ }
+ }
+ else if (this.watertype == CONTENT_SLIME)
+ {
+ // do damage
+ if (this.dmgtime < time && this.radsuit_finished < time)
+ {
+ this.dmgtime = time + 1;
+ this.deathtype = "slime";
+ this.t_damage2 (this, world, world,
+ 4 * this.waterlevel);
+ this.deathtype = "";
+ }
+ }
+
+ if (!(this.flags & FL_INWATER))
+ {
+ // player enter water sound
+ if (this.watertype == CONTENT_LAVA)
+ sound (this, CHAN_BODY, "player/inlava.wav",
+ 1, ATTN_NORM);
+ if (this.watertype == CONTENT_WATER)
+ sound (this, CHAN_BODY, "player/inh2o.wav",
+ 1, ATTN_NORM);
+ if (this.watertype == CONTENT_SLIME)
+ sound (this, CHAN_BODY, "player/slimbrn2.wav",
+ 1, ATTN_NORM);
+
+ this.flags = this.flags + FL_INWATER;
+ this.dmgtime = 0;
+ }
+ };
+
+ //--------------------------------------------------------------
+ // CheckWaterJump -- the legacy standard id1 (?) waterjump
+ //--------------------------------------------------------------
+ nonvirtual void() prethink_waterjump =
+ {
+ // from Copper -- dumptruck_ds
+ if (this.movetype == MOVETYPE_NOCLIP)
+ return;
+
+ local vector start, end;
+
+ // check for a jump-out-of-water
+ makevectors (this.angles);
+ start = this.origin;
+ start_z = start_z + 8;
+ v_forward_z = 0;
+ normalize (v_forward);
+ end = start + v_forward * 24;
+ traceline (start, end, TRUE, this);
+ if (trace_fraction < 1)
+ {
+ // solid at waist
+ start_z = start_z + this.maxs_z - 8;
+ end = start + v_forward * 24;
+ this.movedir = trace_plane_normal * -50;
+ traceline (start, end, TRUE, this);
+ if (trace_fraction == 1)
+ {
+ // open at eye level
+ this.flags = this.flags | FL_WATERJUMP;
+ this.velocity_z = 225;
+ this.flags -= this.flags & FL_JUMPRELEASED;
+ // safety net
+ this.teleport_time = time + 2;
+ return;
+ }
+ }
+ };
+
+ //--------------------------------------------------------------
+ // PlayerJump -- standard legacy id1 jump logic
+ //--------------------------------------------------------------
+ nonvirtual void() prethink_jump =
+ {
+ if (this.flags & FL_WATERJUMP)
+ return;
+
+ if (this.waterlevel >= 2)
+ {
+ if (this.watertype == CONTENT_WATER)
+ this.velocity_z = 100;
+ else if (this.watertype == CONTENT_SLIME)
+ this.velocity_z = 80;
+ else
+ this.velocity_z = 50;
+
+ // play swiming sound
+ if (this.swim_flag < time)
+ {
+ this.swim_flag = time + 1;
+ if (random() < 0.5)
+ sound (this, CHAN_BODY,
+ "misc/water1.wav",
+ 1, ATTN_NORM);
+ else
+ sound (this, CHAN_BODY,
+ "misc/water2.wav",
+ 1, ATTN_NORM);
+ }
+ return;
+ }
+
+ // refactoring from Copper -- dumptruck_ds
+ if (this.movetype != MOVETYPE_NOCLIP)
+ {
+ if (!(this.flags & FL_ONGROUND))
+ return;
+ // don't pogo stick
+ if ( !(this.flags & FL_JUMPRELEASED) )
+ return;
+ // player jumping sound (h00rt)
+ sound (this, CHAN_BODY, "player/plyrjmp8.wav",
+ 1, ATTN_NORM);
+ }
+
+ this.flags = this.flags - (this.flags & FL_JUMPRELEASED);
+
+ // don't stairwalk
+ this.flags = this.flags - FL_ONGROUND;
+
+ this.button2 = 0;
+ this.velocity_z = this.velocity_z + 270;
+ };
+
+ //--------------------------------------------------------------
+ // Called by PlayerPreThink in entrypoints.qc -- CEV
+ //--------------------------------------------------------------
+ nonvirtual void() prethink =
+ {
+ local float do_ladder_physics = FALSE;
+
+ // note that this code block is here, before the tests
+ // which check whether the player is dead, so that the
+ // player's gravity will be correctly updated even if
+ // they e.g. fell off a ladder because they died -- iw
+ if (frame_standardphysics)
+ {
+ if (this.pmove_flags & PMF_ONLADDER)
+ {
+ do_ladder_physics = TRUE;
+ // not zero, because zero means "default"
+ this.gravity = 0.0000001;
+ this.pmove_flags &= ~PMF_ONLADDER;
+ }
+ else
+ {
+ do_ladder_physics = FALSE;
+ this.gravity = this.wantedgravity;
+ }
+
+ // from copper -- dumptruck_ds
+ if (this.movetype == MOVETYPE_NOCLIP)
+ this.flags |= FL_FLY;
+ }
+ else
+ {
+ this.gravity = this.wantedgravity;
+ }
+
+ // If just spawned in, try to recover previous fog values
+ // from own client entity, if any
+ if (cleanUpClientStuff)
+ fog_setFromEnt (this, this);
+
+ // WaterMove - needs to run even if doing nonstandard physics
+ this.prethink_watermove ();
+
+ if (frame_standardphysics)
+ {
+ // run legacy CheckWaterJump if we're doing
+ // standard physics -- CEV
+ if (this.waterlevel == 2)
+ this.prethink_waterjump ();
+
+ // johnfitz ladder conditions, added from
+ // Rubicon2 -- dumptruck_ds
+ if (do_ladder_physics)
+ {
+ if (this.button2)
+ {
+ // PlayerClimb -- johnfitz
+ this.velocity = '0 0 160';
+ /*
+ // no ladder footsteps for now
+ if (time > this.ladder_step_finished)
+ {
+ // TODO CEV oof
+ r = random();
+ if (r > 0.66)
+ sound (this, CHAN_BODY,
+ "ladder/metal1.wav",
+ 0.5, ATTN_NORM);
+ else if (r > 0.33)
+ sound (this, CHAN_BODY,
+ "ladder/metal2.wav",
+ 0.5, ATTN_NORM);
+ else
+ sound (this, CHAN_BODY,
+ "ladder/metal3.wav",
+ 0.5, ATTN_NORM);
+ this.ladder_step_finished =
+ time + 0.3;
+ }
+ */
+ }
+ else
+ {
+ this.flags |= FL_JUMPRELEASED;
+ this.velocity = 0.9 * this.velocity;
+ this.velocity_z = 0;
+ }
+ }
+ else
+ {
+ if (this.button2)
+ this.prethink_jump ();
+ else
+ this.flags |= FL_JUMPRELEASED;
+ }
+ }
+
+ if (this.deadflag >= DEAD_DEAD)
+ {
+ // dead, so run the death think -- CEV
+ this.think_death ();
+ return;
+ }
+
+ if (this.deadflag == DEAD_DYING)
+ // dying, so do nothing
+ return;
+
+ // teleporters can force a non-moving pause time
+ if (time < this.pausetime)
+ this.velocity = '0 0 0';
+
+ if (time > this.attack_finished && this.currentammo == 0
+ && this.weapon != IT_AXE)
+ {
+ this.weapon = this.best_weapon ();
+ this.set_current_ammo ();
+ }
+
+ // TODO CEV
+ if (this.groundboost_timer <= 0 &&
+ (this.teleport_time > time - 0.1))
+ {
+ this.groundboost_timer = PM_GROUNDBOOST_WINDOW;
+ }
+ };
+
+ //--------------------------------------------------------------
+ // CheckPowerups -- Check for turning off powerups
+ //--------------------------------------------------------------
+ nonvirtual void() postthink_powerups =
+ {
+ if (this.health <= 0)
+ return;
+
+ // invisibility
+ if (this.invisible_finished)
+ {
+ // sound and screen flash when items starts to run out
+ if (this.invisible_sound < time)
+ {
+ sound (this, CHAN_AUTO, "items/inv3.wav",
+ 0.5, ATTN_IDLE);
+ invisible_sound = time + ((random() * 3) + 1);
+ }
+
+ if (this.invisible_finished < time + 3)
+ {
+ if (this.invisible_time == 1)
+ {
+ sprint (this, "Ring of Shadows magic is"
+ " fading\n");
+ stuffcmd (this, "bf\n");
+ sound (this, CHAN_AUTO,"items/inv2.wav",
+ 1, ATTN_NORM);
+ this.invisible_time = time + 1;
+ }
+
+ if (this.invisible_time < time)
+ {
+ this.invisible_time = time + 1;
+ stuffcmd (this, "bf\n");
+ }
+ }
+
+ if (this.invisible_finished < time)
+ {
+ // just stopped
+ this.items = this.items - IT_INVISIBILITY;
+ this.invisible_finished = 0;
+ this.invisible_time = 0;
+ }
+
+ // use the eyes
+ this.frame = 0;
+ this.modelindex = modelindex_eyes;
+ }
+ else
+ {
+ // don't use the eyes
+ this.modelindex = modelindex_player;
+ }
+
+ // invincibility
+ if (this.invincible_finished)
+ {
+ // sound and screen flash when items starts to run out
+ if (this.invincible_finished < time + 3)
+ {
+ if (this.invincible_time == 1)
+ {
+ sprint (this, "Protection is almost "
+ "burned out\n");
+ stuffcmd (this, "bf\n");
+ sound (this, CHAN_AUTO,
+ "items/protect2.wav",
+ 1, ATTN_NORM);
+ this.invincible_time = time + 1;
+ }
+
+ if (this.invincible_time < time)
+ {
+ this.invincible_time = time + 1;
+ stuffcmd (this, "bf\n");
+ }
+ }
+
+ if (this.invincible_finished < time)
+ {
+ // just stopped
+ this.items = this.items - IT_INVULNERABILITY;
+ this.invincible_time = 0;
+ this.invincible_finished = 0;
+ }
+ if (this.invincible_finished > time)
+ this.effects = this.effects | EF_DIMLIGHT;
+ else
+ this.effects -= this.effects & EF_DIMLIGHT;
+ }
+
+ // super damage
+ if (this.super_damage_finished)
+ {
+ // sound and screen flash when items starts to run out
+ if (this.super_damage_finished < time + 3)
+ {
+ if (this.super_time == 1)
+ {
+ sprint (this, "Quad Damage is wearing "
+ "off\n");
+ stuffcmd (this, "bf\n");
+ sound (this, CHAN_AUTO,
+ "items/damage2.wav",
+ 1, ATTN_NORM);
+ this.super_time = time + 1;
+ }
+
+ if (this.super_time < time)
+ {
+ this.super_time = time + 1;
+ stuffcmd (this, "bf\n");
+ }
+ }
+
+ if (this.super_damage_finished < time)
+ {
+ // just stopped
+ this.items = this.items - IT_QUAD;
+ this.super_damage_finished = 0;
+ this.super_time = 0;
+ }
+ if (this.super_damage_finished > time)
+ this.effects = this.effects | EF_DIMLIGHT;
+ else
+ this.effects -= this.effects & EF_DIMLIGHT;
+ }
+
+ // suit
+ if (this.radsuit_finished)
+ {
+ // don't drown
+ this.air_finished = time + 12;
+
+ // sound and screen flash when items starts to run out
+ if (this.radsuit_finished < time + 3)
+ {
+ if (this.rad_time == 1)
+ {
+ sprint (this, "Air supply in Biosuit "
+ "expiring\n");
+ stuffcmd (this, "bf\n");
+ sound (this, CHAN_AUTO,
+ "items/suit2.wav",
+ 1, ATTN_NORM);
+ this.rad_time = time + 1;
+ }
+
+ if (this.rad_time < time)
+ {
+ this.rad_time = time + 1;
+ stuffcmd (this, "bf\n");
+ }
+ }
+
+ if (this.radsuit_finished < time)
+ {
+ // just stopped
+ this.items = this.items - IT_SUIT;
+ this.rad_time = 0;
+ this.radsuit_finished = 0;
+ }
+ }
+ };
+
+ //--------------------------------------------------------------
+ // Called by PlayerPostThink in entrypoints.qc -- CEV
+ //--------------------------------------------------------------
+ nonvirtual void() postthink =
+ {
+ if (this.view_ofs == '0 0 0')
+ // intermission or finale
+ return;
+
+ // full send -- CEV
+ this.SendFlags = 0xffffff;
+
+ if (this.deadflag)
+ return;
+
+ // next block was in W_WeaponFrame -- CEV
+ if (time >= this.attack_finished)
+ {
+ if (this.impulse)
+ this.impulse_commands ();
+
+ if (this.button0)
+ {
+ this.superdamage_sound ();
+ this.attack ();
+ }
+ }
+
+ // check to see if player landed and play landing sound
+ if ((this.jump_flag < -300) && (this.flags & FL_ONGROUND) &&
+ (this.health > 0))
+ {
+ if (this.watertype == CONTENT_WATER)
+ sound (this, CHAN_BODY, "player/h2ojump.wav",
+ 1, ATTN_NORM);
+ else if (this.jump_flag < -650)
+ {
+ this.deathtype = "falling";
+ this.t_damage2 (this, world, world, 5);
+ this.deathtype = "";
+ sound (this, CHAN_VOICE, "player/land2.wav",
+ 1, ATTN_NORM);
+ }
+ else
+ sound (this, CHAN_VOICE, "player/land.wav",
+ 1, ATTN_NORM);
+
+ this.jump_flag = 0;
+ }
+
+ if (!(this.flags & FL_ONGROUND))
+ this.jump_flag = this.velocity_z;
+
+ // dumptruck_ds -- this replaces item_megahealth_rot in items.qc
+ if (this.health > this.max_health)
+ {
+ if (this.megahealth_rottime < time)
+ {
+ this.megahealth_rottime = time + 1;
+ this.health = this.health - 1;
+ }
+ else if (this.health <= 100)
+ {
+ // thanks ydrol!!!
+ this.items = this.items -
+ (this.items & IT_SUPERHEALTH);
+ }
+ }
+
+ this.postthink_powerups ();
+
+ // from Copper -- dumptruck_ds
+ if (frame_standardphysics && this.movetype != MOVETYPE_NOCLIP)
+ this.flags &= ~FL_FLY;
+ };
+
+ //==============================================================
+ // Interaction
+ //==============================================================
+
+ //--------------------------------------------------------------
+ // SendEntity -- transmit updates from server to client -- CEV
+ //--------------------------------------------------------------
+ virtual float(entity to, float fl) SendEntity =
+ {
+ WriteByte (MSG_ENTITY, CT_PLAYER);
+ WriteByte (MSG_ENTITY, this.frame);
+ WriteCoord (MSG_ENTITY, this.origin_x);
+ WriteCoord (MSG_ENTITY, this.origin_y);
+ WriteCoord (MSG_ENTITY, this.origin_z);
+ WriteShort (MSG_ENTITY, this.angles_x * 32767 / 360);
+ WriteShort (MSG_ENTITY, this.angles_y * 32767 / 360);
+ WriteShort (MSG_ENTITY, this.angles_z * 32767 / 360);
+ WriteShort (MSG_ENTITY, this.velocity_x);
+ WriteShort (MSG_ENTITY, this.velocity_y);
+ WriteShort (MSG_ENTITY, this.velocity_z);
+ WriteFloat (MSG_ENTITY, this.effects);
+ WriteFloat (MSG_ENTITY, this.flags);
+ WriteFloat (MSG_ENTITY, this.pmove_flags);
+ WriteFloat (MSG_ENTITY, this.doublejump_timer);
+ WriteFloat (MSG_ENTITY, this.groundboost_timer);
+ return TRUE;
+ };
+
+ //--------------------------------------------------------------
+ // player_pain
+ //--------------------------------------------------------------
+ virtual void(entity attacker, float damage) do_damage =
+ {
+ if (this.weaponframe)
+ return;
+
+ if (this.invisible_finished > time)
+ // eyes don't have pain frames
+ return;
+
+ if (this.weapon == IT_AXE)
+ this.axpain1 ();
+ else
+ this.pain1 ();
+ };
+
+ //--------------------------------------------------------------
+ // PlayerDie
+ //--------------------------------------------------------------
+ virtual void() do_destroy =
+ {
+ local float i;
+
+ // 1998-07-23 Palette shift when player dies with quad/pentagram
+ // fix by Maddes start
+ // this.items = this.items - (this.items & IT_INVISIBILITY);
+ this.items = this.items - (this.items &
+ (IT_INVISIBILITY | IT_INVULNERABILITY |
+ IT_SUIT | IT_QUAD));
+ // 1998-07-23 Palette shift when player dies with quad/pentagram
+ // fix by Maddes end
+
+ // don't die as eyes
+ // this.invisible_finished = 0;
+ this.invincible_finished = 0;
+ this.super_damage_finished = 0;
+ this.radsuit_finished = 0;
+
+ // 1998-07-23 Glowing corpse of players which had quad/pentagram
+ // until respawn fix by Maddes
+ this.effects = 0;
+
+ // don't use eyes
+ this.modelindex = modelindex_player;
+
+ if (deathmatch || coop)
+ item_backpack::drop_backpack (this.origin, this.weapon,
+ this.ammo_shells, this.ammo_nails,
+ this.ammo_rockets, this.ammo_cells);
+
+ this.weaponmodel = "";
+ this.view_ofs = '0 0 -8';
+ this.deadflag = DEAD_DYING;
+ this.solid = SOLID_NOT;
+ this.flags = this.flags - (this.flags & FL_ONGROUND);
+ this.movetype = MOVETYPE_TOSS;
+
+ if (this.velocity_z < 10)
+ this.velocity_z = this.velocity_z + random() * 300;
+
+ if (this.health < -40)
+ {
+ GibPlayer ();
+ return;
+ }
+
+ this.death_sound ();
+
+ this.angles_x = 0;
+ this.angles_z = 0;
+
+ if (this.weapon == IT_AXE)
+ {
+ this.die_ax1 ();
+ return;
+ }
+
+ i = cvar ("temp1");
+ if (!i)
+ i = 1 + floor (random() * 6);
+
+ if (i == 1)
+ this.diea1 ();
+ else if (i == 2)
+ this.dieb1 ();
+ else if (i == 3)
+ this.diec1 ();
+ else if (i == 4)
+ this.died1 ();
+ else
+ this.diee1 ();
+ };
+
+ //--------------------------------------------------------------
+ // by: Philip Martin aka: Kryten
+ // When on top of monsters or players you slide. This is a QuakeC
+ // problem. The function below fixes that problem.
+ // based on code given to Kryten by: Michael Turitzin (MaNiAc)
+ //--------------------------------------------------------------
+ virtual void() touch =
+ {
+ // 1998-09-16 Sliding/not-jumping on monsters/boxes/players
+ // fix by Maddes/Kryten start
+
+ // can cause problems for monsters on top of a player,
+ // so only players
+ if (other.classtype != CT_PLAYER)
+ return;
+ if (other.health <= 0)
+ return;
+
+ if ((!(other.flags & FL_ONGROUND)) &&
+ ((other.absmin_z >= this.absmax_z - 2)))
+ {
+ other.flags = other.flags + FL_ONGROUND;
+ }
+
+ // you can add other stuff like pushable players/monsters here
+
+ // 1998-09-16 Sliding/not-jumping on monsters/boxes/players
+ // fix by Maddes/Kryten end
+ };
+
+ //==============================================================
+ // Initialization
+ //==============================================================
+
+ //--------------------------------------------------------------
+ // SelectSpawnPoint -- Returns the entity to spawn at
+ //--------------------------------------------------------------
+ nonvirtual entity() init_select_spawn_point =
+ {
+ local entity spot, thing;
+ local float pcount;
+
+ // testinfo_player_start is only found in regioned levels
+ spot = findfloat (world, ::classtype, CT_INFO_TESTPLAYERSTART);
+ if (spot)
+ return spot;
+
+ // choose a info_player_deathmatch point
+ if (coop)
+ {
+ lastspawn = findfloat (lastspawn, ::classtype,
+ CT_INFO_PLAYER_COOP);
+ if (lastspawn == world)
+ lastspawn = findfloat (lastspawn, ::classtype,
+ CT_INFO_PLAYER_START);
+ if (lastspawn != world)
+ return lastspawn;
+ }
+ else if (deathmatch)
+ {
+ spot = lastspawn;
+ // TODO CEV this loops infinitely if no
+ // info_player_deathmatch
+ while (1)
+ {
+ spot = findfloat (spot, ::classtype,
+ CT_INFO_PLAYER_DEATHMATCH);
+ if (spot != world)
+ {
+ if (spot == lastspawn)
+ return lastspawn;
+ pcount = 0;
+ thing = findradius (spot.origin, 32);
+ while (thing)
+ {
+ if (thing.classtype==CT_PLAYER)
+ pcount = pcount + 1;
+ thing = thing.chain;
+ }
+ if (pcount == 0)
+ {
+ lastspawn = spot;
+ return spot;
+ }
+ }
+ }
+ }
+
+ if (serverflags)
+ {
+ // return with a rune to start
+ spot = findfloat (world, ::classtype,
+ CT_INFO_PLAYER_START2);
+ if (spot)
+ return spot;
+ }
+
+ spot = findfloat (world, ::classtype, CT_INFO_PLAYER_START);
+ if (!spot)
+ error ("PutClientInServer: no info_player_start "
+ "on level");
+
+ return spot;
+ };
+
+ //--------------------------------------------------------------
+ nonvirtual void() init_level_parms =
+ {
+ // Reset the player's inventory if they returned to the
+ // start map with a rune, or if the mapper set the
+ // "reset_items" field of worldspawn to a non-zero value.
+ // (The old "reset_items" check, which this replaces,
+ // had a comment from dumptruck_ds thanking Spike.) -- iw
+ if ((serverflags != 0 && world.model == "maps/start.bsp") ||
+ world.reset_items != 0)
+ {
+ SetNewParms ();
+ }
+
+ this.items = parm1;
+ this.health = parm2;
+ this.armorvalue = parm3;
+ this.ammo_shells = parm4;
+ this.ammo_nails = parm5;
+ this.ammo_rockets = parm6;
+ this.ammo_cells = parm7;
+ this.weapon = parm8;
+ this.armortype = parm9 * 0.01;
+ };
+
+ //--------------------------------------------------------------
+ // respawn -- called by ClientKill and DeadThink
+ //--------------------------------------------------------------
+ nonvirtual void() init_respawn =
+ {
+ if (coop)
+ {
+ // make a copy of the dead body for appearances sake
+ CopyToBodyQue (this);
+ // get the spawn parms as they were at level start
+ setspawnparms (this);
+ // respawn
+ this.init_spawned ();
+ }
+ else if (deathmatch)
+ {
+ // make a copy of the dead body for appearances sake
+ CopyToBodyQue (this);
+ // set default spawn parms
+ SetNewParms ();
+ // respawn
+ this.init_spawned ();
+ }
+ else
+ {
+ // restart the entire server
+ localcmd ("restart\n");
+ }
+ };
+
+ //--------------------------------------------------------------
+ // most of this was previously in PutClientInServer -- CEV
+ //--------------------------------------------------------------
+ virtual void() init_spawned =
+ {
+ local entity spot;
+
+ spot = this.init_select_spawn_point ();
+
+ this.health = 100;
+ this.takedamage = DAMAGE_AIM;
+ this.solid = SOLID_SLIDEBOX;
+ // this.solid = SOLID_BBOX;
+ this.movetype = MOVETYPE_WALK;
+ this.show_hostile = 0;
+ this.max_health = 100;
+ this.flags = FL_CLIENT;
+ this.air_finished = time + 12;
+ // initial water damage
+ this.dmg = 2;
+ this.super_damage_finished = 0;
+ this.radsuit_finished = 0;
+ this.invisible_finished = 0;
+ this.invincible_finished = 0;
+ this.effects = 0;
+ this.invincible_time = 0;
+ this.deathtype = "";
+ this.gravity = 0;
+ this.wantedgravity = 0;
+ // support for item_key_custom -- iw
+ this.customkeys = 0;
+
+ // Setup cutscene stuff. Legacy code from Zerstorer.
+ // -- dumptruck_ds
+ this.script_count = 2;
+ this.script_delay = 1;
+ this.script_time = 0;
+
+ this.init_level_parms ();
+ this.set_current_ammo ();
+
+ this.attack_finished = time;
+ this.th_pain = this.do_damage;
+ this.th_die = this.do_destroy;
+ this.deadflag = DEAD_NO;
+ // pausetime is set by teleporters to keep the player
+ // from moving for a while
+ this.pausetime = 0;
+
+ this.origin = spot.origin + '0 0 1';
+ this.angles = spot.angles;
+ // turn this way immediately
+ this.fixangle = TRUE;
+
+ // fog control.
+ // Looks if there's any fog values set at the current
+ // spawn point. If not, looks for those in worldspawn instead
+ if (spot.fog_density)
+ fog_save (this, spot.fog_density, spot.fog_color);
+ else if (world.fog_density)
+ fog_save (this, world.fog_density, world.fog_color);
+
+ if (spot.skyfog_density)
+ skyfog_save (this, spot.skyfog_density);
+ else if (world.skyfog_density)
+ skyfog_save (this, world.skyfog_density);
+
+ // decreased on subsequent frames, used to start some
+ // fog-related stuff
+ cleanUpClientStuff = 2;
+
+ // oh, this is a hack!
+ setmodel (this, "progs/eyes.mdl");
+ modelindex_eyes = this.modelindex;
+
+ // Drake -- dumptruck_ds
+ setmodel (this, "progs/s_null.spr");
+ // Drake -- dumptruck_ds
+ // setmodel (this, "progs/null_256.spr");
+ mindex_inviso = this.modelindex;
+
+ setmodel (this, "progs/player.mdl");
+ modelindex_player = this.modelindex;
+
+ setsize (this, VEC_HULL_MIN, VEC_HULL_MAX);
+
+ this.view_ofs = '0 0 22';
+ // Mod - Xian (May.20.97)
+ // Bug where player would have velocity from their last kill
+ this.velocity = '0 0 0';
+ // 1998-07-21 Player moves after respawn fix by Xian
+
+ this.SendFlags = 0xffffff;
+
+ this.stand1 ();
+
+ if (deathmatch || coop)
+ {
+ makevectors (this.angles);
+ spawn_tfog (this.origin + v_forward*20);
+ }
+
+ spawn_tdeath (this.origin, this);
+ };
+
+ //--------------------------------------------------------------
+ void() player =
+ {
+ this.classname = "player";
+ this.classtype = CT_PLAYER;
+
+ // this isn't a subclass of base_mapentity so we need
+ // to call init_spawned manually -- CEV
+ this.init_spawned ();
+ };
+};
+
+//==============================================================================
+//==============================================================================
+//==============================================================================
+//==============================================================================
+//==============================================================================
+//==============================================================================
+//==============================================================================
+//==============================================================================
+
+//----------------------------------------------------------------------
+void() PlayerDeathBubblesSpawn =
+{
+ local temp_bubbles bubble;
+ if (self.owner.waterlevel != WATERLEVEL_EYES && self.owner.health > 0)
+ {
+ // 1998-08-14 Improved bubble spawn by Maddes
+ // 1998-08-14 Bubblespawner remove fix by Perged start
+ // remove bubble spawner
+ remove (self);
+ // 1998-08-14 Bubblespawner remove fix by Perged end
+ return;
+ // 1998-08-14 Bubblespawner remove fix by Perged
+ }
+
+ bubble = spawn (temp_bubbles, origin: self.owner.origin + '0 0 24');
+ // 1998-08-14 Improved bubble spawn by Maddes start
+ // self.nextthink = time + 0.1;
+ self.nextthink = time + 0.01;
+ // 1998-08-14 Improved bubble spawn by Maddes end
+ self.think = PlayerDeathBubblesSpawn;
+ self.air_finished = self.air_finished + 1;
+ if (self.air_finished >= self.bubble_count)
+ remove (self);
+};
+
+//----------------------------------------------------------------------
+void(float num_bubbles) PlayerDeathBubbles =
+{
+ local entity bubble_spawner;
+
+ bubble_spawner = spawn ();
+ setorigin (bubble_spawner, self.origin);
+ bubble_spawner.movetype = MOVETYPE_NONE;
+ bubble_spawner.solid = SOLID_NOT;
+ // 1998-08-14 Improved bubble spawn by Maddes start
+ // bubble_spawner.nextthink = time + 0.1;
+ bubble_spawner.nextthink = time + 0.01;
+ // 1998-08-14 Improved bubble spawn by Maddes end
+ bubble_spawner.think = PlayerDeathBubblesSpawn;
+ bubble_spawner.air_finished = 0;
+ bubble_spawner.owner = self;
+ bubble_spawner.bubble_count = num_bubbles;
+ // return; // 1998-08-14 unnecessary by Maddes
+};
+
+//==============================================================================
+// Player Gibs
+//==============================================================================
+
+//----------------------------------------------------------------------
+vector(float dm) VelocityForDamage =
+{
+ local vector v;
+
+ v_x = 100 * crandom ();
+ v_y = 100 * crandom ();
+ v_z = 200 + 100 * random ();
+
+ if (dm > -50)
+ {
+ // dprint ("level 1\n");
+ v = v * 0.7;
+ }
+ else if (dm > -200)
+ {
+ // dprint ("level 3\n");
+ v = v * 2;
+ }
+ else
+ {
+ v = v * 10;
+ }
+
+ return v;
+};
+
+//----------------------------------------------------------------------
+void(string gibname, float dm) ThrowGib =
+{
+ local entity new;
+
+ new = spawn ();
+ new.origin = self.origin;
+ setmodel (new, gibname);
+ setsize (new, '0 0 0', '0 0 0');
+ new.velocity = VelocityForDamage (dm);
+ new.movetype = MOVETYPE_BOUNCE;
+ new.solid = SOLID_NOT;
+ new.avelocity_x = random() * 600;
+ new.avelocity_y = random() * 600;
+ new.avelocity_z = random() * 600;
+ new.think = sub_remove;
+ new.ltime = time;
+ new.nextthink = time + 10 + random() * 10;
+ new.frame = 0;
+ new.flags = 0;
+};
+
+//----------------------------------------------------------------------
+void(string gibname, float dm) ThrowHead =
+{
+ setmodel (self, gibname);
+
+ // dumptruck_ds custom_mdl changes
+ self.skin = self.skin_head;
+ if !(self.skin_head)
+ self.skin_head = 0;
+ // end dumptruck_ds
+
+ self.frame = 0;
+ self.nextthink = -1;
+ self.movetype = MOVETYPE_BOUNCE;
+ self.takedamage = DAMAGE_NO;
+ self.solid = SOLID_NOT;
+ self.view_ofs = '0 0 8';
+ setsize (self, '-16 -16 0', '16 16 56');
+ self.velocity = VelocityForDamage (dm);
+ self.origin_z = self.origin_z - 24;
+ self.flags = self.flags - (self.flags & FL_ONGROUND);
+ self.avelocity = crandom() * '0 600 0';
+};
+
+//----------------------------------------------------------------------
+void() GibPlayer =
+{
+ ThrowHead ("progs/h_player.mdl", self.health);
+ ThrowGib ("progs/gib1.mdl", self.health);
+ ThrowGib ("progs/gib2.mdl", self.health);
+ ThrowGib ("progs/gib3.mdl", self.health);
+
+ self.deadflag = DEAD_DEAD;
+
+ if (damage_attacker.classname == "teledeath")
+ {
+ sound (self, CHAN_VOICE, "player/teledth1.wav", 1, ATTN_NONE);
+ return;
+ }
+
+ if (damage_attacker.classname == "teledeath2")
+ {
+ sound (self, CHAN_VOICE, "player/teledth1.wav", 1, ATTN_NONE);
+ return;
+ }
+
+ if (random() < 0.5)
+ sound (self, CHAN_VOICE, "player/gib.wav", 1, ATTN_NONE);
+ else
+ sound (self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NONE);
+};
+
+//======================================================================
+// Scenic Dead Monster Patch stuff here from DeadStuff mod -- dumptruck_ds
+//======================================================================
+
+/*QUAKED player_dead_axe (0 0.5 0.8) (-16 -16 -24) (16 16 32) SOLID X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+{
+ model ({"path":"progs/player.mdl","frame":49});
+}
+*/
+void() player_dead_axe =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ precache_model ("progs/player.mdl");
+ setmodel (self, "progs/player.mdl");
+ self.frame = $axdeth9;
+
+ if (self.spawnflags & 1)
+ {
+ self.solid = SOLID_BBOX;
+ setsize (self,'-38.72 -5.83 -50.45','28.73 33.85 30');
+ }
+ else
+ {
+ self.solid = SOLID_NOT;
+ }
+};
+
+/*QUAKED player_dead_face_down (0 0.5 0.8) (-16 -16 -24) (16 16 32) SOLID X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+{
+ model ({"path":"progs/player.mdl","frame":84});
+}
+*/
+void() player_dead_face_down =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ precache_model ("progs/player.mdl");
+ setmodel (self, "progs/player.mdl");
+ self.frame = $deathc14;
+
+ if (self.spawnflags & 1)
+ {
+ self.solid = SOLID_BBOX;
+ setsize (self,'-50.28 -23.55 -49.85','30.66 14.49 30');
+ }
+ else
+ {
+ self.solid = SOLID_NOT;
+ }
+};
+
+/*QUAKED player_dead_on_side (0 0.5 0.8) (-16 -16 -24) (16 16 32) SOLID X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+{
+ model ({"path":"progs/player.mdl","frame":102});
+}
+*/
+void() player_dead_on_side =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ precache_model ("progs/player.mdl");
+ setmodel (self, "progs/player.mdl");
+ self.frame = $deathe9;
+
+ if (self.spawnflags & 1)
+ {
+ self.solid = SOLID_BBOX;
+ setsize (self,'-38.72 -5.83 -50.45','28.73 33.85 30');
+ }
+ else
+ {
+ self.solid = SOLID_NOT;
+ }
+};
+
+//======================================================================
+// END Scenic Dead Monster Patch stuff here from DeadStuff mod -- dumptruck_ds
+//======================================================================
Return to the top of this page or return to the overview of this repo.
Diff qc/monsters/shalrath.qc
diff --git a/qc/monsters/shalrath.qc b/qc/monsters/shalrath.qc
index 76b9387..cac98b2 100644
--- a/qc/monsters/shalrath.qc
+++ b/qc/monsters/shalrath.qc
@@ -85,68 +85,6 @@ homing(float) : "Amount that the projectile should home in target. 1 is default,
class monster_shalrath: base_walkmonster
{
//--------------------------------------------------------------
- // ShalMissile
- //--------------------------------------------------------------
- nonvirtual void() attack_missile =
- {
- local entity missile;
- local vector dir;
- local float dist, flytime;
-
- dir = normalize ((this.enemy.origin + '0 0 10') - this.origin);
- dist = vlen (this.enemy.origin - this.origin);
- flytime = dist * 0.002 * (1 / this.proj_speed_mod);
- if (flytime < 0.1)
- flytime = 0.1;
-
- this.effects = this.effects | EF_MUZZLEFLASH;
- sound_misc (this, CHAN_WEAPON, "shalrath/attack2.wav",
- 1, ATTN_NORM);
-
- missile = spawn ();
- missile.owner = this;
-
- missile.solid = SOLID_BBOX;
- missile.movetype = MOVETYPE_FLYMISSILE;
-
- // dumptruck_ds custom_mdls
- if (this.mdl_proj != "")
- setmodel (missile, this.mdl_proj);
- else
- setmodel (missile, "progs/v_spike.mdl");
-
- // dumptruck_ds
- if (!missile.skin_proj)
- missile.skin = this.skin_proj;
- else
- missile.skin = 0;
-
- // setmodel (missile, "progs/v_spike.mdl");
-
- setsize (missile, '0 0 0', '0 0 0');
-
- missile.origin = this.origin + '0 0 10';
- SetSpeed (missile, dir, 400 * this.proj_speed_mod);
- // custom spin on projectile -- dumptruck_ds
- missile.avelocity = this.avelocity;
- if !(missile.avelocity)
- missile.avelocity = '300 300 300';
- // If homing is off, don't bother doing any thinking
- if (this.homing > 0)
- {
- missile.homing = this.homing;
- missile.nextthink = flytime + time;
- missile.think = MissileHome;
- }
- if (skill == 3)
- missile.proj_basespeed = 350 * this.proj_speed_mod;
- else
- missile.proj_basespeed = 250 * this.proj_speed_mod;
- missile.enemy = this.enemy;
- missile.touch = ShalMissileTouch;
- };
-
- //--------------------------------------------------------------
virtual void() ai_sightsound =
{
sound_sight (this, CHAN_VOICE, "shalrath/sight.wav",
@@ -218,7 +156,11 @@ class monster_shalrath: base_walkmonster
nonvirtual void() attack6 = [$attack6, attack7] { ai_face (); };
nonvirtual void() attack7 = [$attack7, attack8] { ai_face (); };
nonvirtual void() attack8 = [$attack8, attack9] { ai_face (); };
- nonvirtual void() attack9 = [$attack9, attack10] { attack_missile (); };
+ nonvirtual void() attack9 = [$attack9, attack10]
+ {
+ fire_voreball (this.origin + '0 0 10',
+ (this.enemy.origin + '0 0 10') - this.origin);
+ };
nonvirtual void() attack10 = [$attack10, attack11] { ai_face (); };
nonvirtual void() attack11 = [$attack11, run1] { };
@@ -229,29 +171,30 @@ class monster_shalrath: base_walkmonster
//--------------------------------------------------------------
// Shalrath Turret Attack
//--------------------------------------------------------------
- nonvirtual void() turret_atk1 = [$attack1, turret_atk2]
+ nonvirtual void() tur_atk1 = [$attack1, tur_atk2]
{
sound_attack (this, CHAN_VOICE, "shalrath/attack.wav",
1, ATTN_NORM);
ai_face ();
};
- nonvirtual void() turret_atk2 = [$attack2, turret_atk3] { ai_face (); };
- nonvirtual void() turret_atk3 = [$attack3, turret_atk4] { ai_face (); };
- nonvirtual void() turret_atk4 = [$attack4, turret_atk5] { ai_face (); };
- nonvirtual void() turret_atk5 = [$attack5, turret_atk6] { ai_face (); };
- nonvirtual void() turret_atk6 = [$attack6, turret_atk7] { ai_face (); };
- nonvirtual void() turret_atk7 = [$attack7, turret_atk8] { ai_face (); };
- nonvirtual void() turret_atk8 = [$attack8, turret_atk9] { ai_face (); };
- nonvirtual void() turret_atk9 = [$attack9, turret_atk10]
+ nonvirtual void() tur_atk2 = [$attack2, tur_atk3] { ai_face (); };
+ nonvirtual void() tur_atk3 = [$attack3, tur_atk4] { ai_face (); };
+ nonvirtual void() tur_atk4 = [$attack4, tur_atk5] { ai_face (); };
+ nonvirtual void() tur_atk5 = [$attack5, tur_atk6] { ai_face (); };
+ nonvirtual void() tur_atk6 = [$attack6, tur_atk7] { ai_face (); };
+ nonvirtual void() tur_atk7 = [$attack7, tur_atk8] { ai_face (); };
+ nonvirtual void() tur_atk8 = [$attack8, tur_atk9] { ai_face (); };
+ nonvirtual void() tur_atk9 = [$attack9, tur_atk10]
{
- attack_missile ();
+ fire_voreball (this.origin + '0 0 10',
+ (this.enemy.origin + '0 0 10') - this.origin);
};
- nonvirtual void() turret_atk10 = [$attack10, turret_atk11] {ai_face();};
- nonvirtual void() turret_atk11 = [$attack11, turret_atk12] {ai_face();};
- nonvirtual void() turret_atk12 = [$walk1, turret_atk13] { ai_face (); };
- nonvirtual void() turret_atk13 = [$walk1, turret_atk14] { ai_face (); };
- nonvirtual void() turret_atk14 = [$walk1, turret_atk15] { ai_face (); };
- nonvirtual void() turret_atk15 = [$walk1, seek_stand1] { ai_run (0); };
+ nonvirtual void() tur_atk10 = [$attack10, tur_atk11] {ai_face();};
+ nonvirtual void() tur_atk11 = [$attack11, tur_atk12] {ai_face();};
+ nonvirtual void() tur_atk12 = [$walk1, tur_atk13] { ai_face (); };
+ nonvirtual void() tur_atk13 = [$walk1, tur_atk14] { ai_face (); };
+ nonvirtual void() tur_atk14 = [$walk1, tur_atk15] { ai_face (); };
+ nonvirtual void() tur_atk15 = [$walk1, seek_stand1] { ai_run (0); };
//--------------------------------------------------------------
// Shalrath Turret Standing/Seeeking
@@ -432,12 +375,7 @@ class monster_shalrath: base_walkmonster
else
this.th_pain = sub_nullpain;
this.think_missile = this.attack1;
- this.think_turret = this.turret_atk1;
-
- /*
- this.think = walkmonster_start;
- this.nextthink = time + 0.1 + random ()*0.1;
- */
+ this.think_turret = this.tur_atk1;
// call walkmonster_start directly -- CEV
super::init_spawned ();
@@ -450,32 +388,6 @@ class monster_shalrath: base_walkmonster
};
};
-// ShalMissileTouch --moved to misc.qc for voreball shooter -- dumptruck-ds
-/*
-void() ShalMissileTouch =
-{
- if (other == self.owner)
- return; // don't explode on owner
-
- if (other.classname == "monster_zombie")
- T_Damage (other, self, self, 110);
- T_RadiusDamage (self, self.owner, 40, world);
- sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
-
- 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);
-
- self.velocity = '0 0 0';
- self.touch = sub_null;
- setmodel (self, "progs/s_explod.spr");
- self.solid = SOLID_NOT;
- s_explode1 ();
-};
-*/
-
//==============================================================================
/* Scenic Dead Monster Patch stuff here from DeadStuff mod -- dumptruck_ds */
Return to the top of this page or return to the overview of this repo.
Diff qc/monsters/shambler.qc
diff --git a/qc/monsters/shambler.qc b/qc/monsters/shambler.qc
index 0a36b06..dbec299 100644
--- a/qc/monsters/shambler.qc
+++ b/qc/monsters/shambler.qc
@@ -128,7 +128,7 @@ class monster_shambler: base_walkmonster
if (enemy_range == RANGE_MELEE)
{
- if (CanDamage(this.enemy, this))
+ if (this.can_damage(this, this.enemy))
{
this.attack_state = AS_MELEE;
return TRUE;
@@ -208,7 +208,7 @@ class monster_shambler: base_walkmonster
return;
ldmg = (random() + random() + random()) * 20;
- T_Damage (this.enemy, this, this, ldmg);
+ this.t_damage2 (this.enemy, this, this, ldmg);
sound_hit (this, CHAN_VOICE, "shambler/smack.wav",
1, ATTN_NORM);
@@ -255,73 +255,19 @@ class monster_shambler: base_walkmonster
WriteCoord (MSG_BROADCAST, trace_endpos_y);
WriteCoord (MSG_BROADCAST, trace_endpos_z);
- LightningDamage (org, trace_endpos, this, 10);
+ weapon_lightning::lightning_damage (org, trace_endpos, this, 10);
};
//--------------------------------------------------------------
// ShamRocket
//--------------------------------------------------------------
- nonvirtual void() attack_rocket =
+ nonvirtual void() attack_lavaball =
{
- local entity missile;
- local float projspeed = 900 * this.proj_speed_mod;
-
sound_attack (this, CHAN_AUTO, "boss1/throw.wav", 1, ATTN_NORM);
- missile = spawn ();
- missile.owner = this;
- missile.movetype = MOVETYPE_FLYMISSILE;
- missile.solid = SOLID_BBOX;
- missile.classname = "missile";
-
- // set missile speed -- dumptruck_ds below
-
- SetSpeed (missile, normalize(this.enemy.origin - this.origin),
- projspeed);
- missile.angles = vectoangles (missile.velocity);
- // custom spin of projectile
- missile.avelocity = this.cust_avelocity;
- if !(missile.avelocity)
- missile.avelocity = '200 100 300';
-
- missile.touch = T_MissileTouch;
-
- // set missile duration
- if (this.homing > 0)
- {
- SetupHoming (missile, projspeed);
- }
- else
- {
- missile.nextthink = time + 5;
- missile.think = sub_remove;
- }
- // dumptruck_ds
- missile.skin = this.skin_proj;
-
- // dumptruck_ds
- if (this.mdl_proj != "")
- {
- setmodel (missile, this.mdl_proj);
- }
- else
- {
- setmodel (missile, "progs/lavaball.mdl");
- }
-
- // dumptruck_ds
- if (!missile.skin_proj)
- {
- missile.skin = this.skin_proj;
- }
- else
- {
- missile.skin = 0;
- }
- setsize (missile, '0 0 0', '0 0 0');
- // thanks Voidforce -- dumptruck_ds
- makevectors (this.angles);
- setorigin (missile, this.origin + v_forward*8 + '0 0 24');
+ // custom lavaball speed -- CEV
+ fire_lavaball (this.origin + v_forward * 8 + '0 0 24',
+ this.enemy.origin - this.origin, 900);
};
//--------------------------------------------------------------
@@ -442,11 +388,11 @@ class monster_shambler: base_walkmonster
if (vlen(delta) > 100)
return;
- if (!CanDamage(this.enemy, this))
+ if (!this.can_damage(this, this.enemy))
return;
ldmg = (random() + random() + random()) * 40;
- T_Damage (this.enemy, this, this, ldmg);
+ this.t_damage2 (this.enemy, this, this, ldmg);
sound_hit (this, CHAN_VOICE, "shambler/smack.wav",
1, ATTN_NORM);
@@ -476,7 +422,7 @@ class monster_shambler: base_walkmonster
nonvirtual void() proj9 = [$smash9, proj10] { ai_face (); };
nonvirtual void() proj10 = [$smash10, proj11]
{
- this.attack_rocket ();
+ this.attack_lavaball ();
sound_attack (this, CHAN_VOICE, "shambler/melee1.wav",
1, ATTN_NORM);
ai_face ();
@@ -488,24 +434,24 @@ class monster_shambler: base_walkmonster
//--------------------------------------------------------------
// Shambler Projectile (Turret Mode)
//--------------------------------------------------------------
- nonvirtual void() turret_proj1 = [$smash1, turret_proj2] { ai_face (); };
- nonvirtual void() turret_proj2 = [$smash2, turret_proj3] { ai_face (); };
- nonvirtual void() turret_proj3 = [$smash3, turret_proj4] { ai_face (); };
- nonvirtual void() turret_proj4 = [$smash4, turret_proj5] { ai_face (); };
- nonvirtual void() turret_proj5 = [$smash5, turret_proj6] { ai_face (); };
- nonvirtual void() turret_proj6 = [$smash6, turret_proj7] { ai_face (); };
- nonvirtual void() turret_proj7 = [$smash7, turret_proj8] { ai_face (); };
- nonvirtual void() turret_proj8 = [$smash8, turret_proj9] { ai_face (); };
- nonvirtual void() turret_proj9 = [$smash9, turret_proj10] { ai_face (); };
- nonvirtual void() turret_proj10 = [$smash10, turret_proj11]
- {
- this.attack_rocket ();
+ nonvirtual void() tur_proj1 = [$smash1, tur_proj2] { ai_face (); };
+ nonvirtual void() tur_proj2 = [$smash2, tur_proj3] { ai_face (); };
+ nonvirtual void() tur_proj3 = [$smash3, tur_proj4] { ai_face (); };
+ nonvirtual void() tur_proj4 = [$smash4, tur_proj5] { ai_face (); };
+ nonvirtual void() tur_proj5 = [$smash5, tur_proj6] { ai_face (); };
+ nonvirtual void() tur_proj6 = [$smash6, tur_proj7] { ai_face (); };
+ nonvirtual void() tur_proj7 = [$smash7, tur_proj8] { ai_face (); };
+ nonvirtual void() tur_proj8 = [$smash8, tur_proj9] { ai_face (); };
+ nonvirtual void() tur_proj9 = [$smash9, tur_proj10] { ai_face (); };
+ nonvirtual void() tur_proj10 = [$smash10, tur_proj11]
+ {
+ this.attack_lavaball ();
sound_attack (this, CHAN_VOICE, "shambler/melee1.wav",
1, ATTN_NORM);
ai_face();
};
- nonvirtual void() turret_proj11 = [$smash11, turret_proj12] { ai_face (); };
- nonvirtual void() turret_proj12 = [$smash12, seek_1] { ai_face (); };
+ nonvirtual void() tur_proj11 = [$smash11, tur_proj12] { ai_face (); };
+ nonvirtual void() tur_proj12 = [$smash12, seek_1] { ai_face (); };
/////////////////////////////////////
// end projectile style frames //
@@ -633,14 +579,14 @@ class monster_shambler: base_walkmonster
//--------------------------------------------------------------
// ~Shambler Turret Magic~
//--------------------------------------------------------------
- nonvirtual void() turret_magic1 = [$magic1, turret_magic2]
+ nonvirtual void() tur_magic1 = [$magic1, tur_magic2]
{
ai_face ();
sound_misc1 (this, CHAN_WEAPON, "shambler/sattck1.wav",
1, ATTN_NORM);
};
- nonvirtual void() turret_magic2 = [$magic2, turret_magic3] {ai_face();};
- nonvirtual void() turret_magic3 = [$magic3, turret_magic4]
+ nonvirtual void() tur_magic2 = [$magic2, tur_magic3] {ai_face();};
+ nonvirtual void() tur_magic3 = [$magic3, tur_magic4]
{
ai_face ();
this.nextthink = time + 0.2;
@@ -657,17 +603,17 @@ class monster_shambler: base_walkmonster
o.nextthink = time + 0.7;
o.think = sham_arc_think;
};
- nonvirtual void() turret_magic4 = [$magic4, turret_magic5]
+ nonvirtual void() tur_magic4 = [$magic4, tur_magic5]
{
this.effects = this.effects | EF_MUZZLEFLASH;
this.trigger_field.frame = 1;
};
- nonvirtual void() turret_magic5 = [$magic5, turret_magic6]
+ nonvirtual void() tur_magic5 = [$magic5, tur_magic6]
{
this.effects = this.effects | EF_MUZZLEFLASH;
this.trigger_field.frame = 2;
};
- nonvirtual void() turret_magic6 = [$magic6, turret_magic9]
+ nonvirtual void() tur_magic6 = [$magic6, tur_magic9]
{
remove (this.trigger_field);
this.trigger_field = world;
@@ -675,33 +621,33 @@ class monster_shambler: base_walkmonster
sound_misc2 (this, CHAN_WEAPON, "shambler/sboom.wav",
1, ATTN_NORM);
};
- nonvirtual void() turret_magic9 = [$magic9, turret_magic10]
+ nonvirtual void() tur_magic9 = [$magic9, tur_magic10]
{
this.attack_lightning ();
};
- nonvirtual void() turret_magic10 = [$magic10, turret_magic11]
+ nonvirtual void() tur_magic10 = [$magic10, tur_magic11]
{
this.attack_lightning ();
};
- nonvirtual void() turret_magic11 = [$magic11, turret_magic12]
+ nonvirtual void() tur_magic11 = [$magic11, tur_magic12]
{
if (skill == 3)
this.attack_lightning ();
};
- nonvirtual void() turret_magic12 =[ $magic12, turret_magic13] { };
- nonvirtual void() turret_magic13 =[ $stand14, turret_magic14]
+ nonvirtual void() tur_magic12 =[ $magic12, tur_magic13] { };
+ nonvirtual void() tur_magic13 =[ $stand14, tur_magic14]
{
ai_face ();
};
- nonvirtual void() turret_magic14 =[ $stand15, turret_magic15]
+ nonvirtual void() tur_magic14 =[ $stand15, tur_magic15]
{
ai_face ();
};
- nonvirtual void() turret_magic15 =[ $stand16, turret_magic16]
+ nonvirtual void() tur_magic15 =[ $stand16, tur_magic16]
{
ai_face ();
};
- nonvirtual void() turret_magic16 =[ $stand17, seek_1] { };
+ nonvirtual void() tur_magic16 =[ $stand17, seek_1] { };
//--------------------------------------------------------------
// Shambler Turret Seeking state (tracking target?)
@@ -920,9 +866,9 @@ class monster_shambler: base_walkmonster
else
this.think_missile = this.magic1;
if (this.style == 1)
- this.think_turret = this.turret_proj1;
+ this.think_turret = this.tur_proj1;
else
- this.think_turret = this.turret_magic1;
+ this.think_turret = this.tur_magic1;
// Berserk test from
// http://celephais.net/board/view_thread.php?id=4&start=3465
// -- dumptruck_ds
Return to the top of this page or return to the overview of this repo.
Diff qc/monsters/soldier.qc
diff --git a/qc/monsters/soldier.qc b/qc/monsters/soldier.qc
index 7d6188a..6e43c72 100644
--- a/qc/monsters/soldier.qc
+++ b/qc/monsters/soldier.qc
@@ -190,40 +190,71 @@ class monster_army: base_walkmonster
//--------------------------------------------------------------
nonvirtual void() army_fire =
{
- // TODO CEV this will need to be re-checked soon
- /*
// dumptruck_ds start rocket grunt stuff
if (this.style == 1)
{
+ // Rocket
ai_face ();
- W_GruntRocket ();
+ makevectors (this.angles);
+ // org, dir, direct_damage, splash_damage, speed
+ fire_rocket (this.origin +
+ (v_forward * 30 + v_right * 5 + '0 0 12'),
+ this.enemy.origin - this.origin, 30, 40, 900);
}
else if (this.style == 2)
{
+ // Grenade
ai_face ();
+ // TODO CEV calling makevectors here & then again in
+ // fire_grenade below is not ideal
+ makevectors (this.angles);
+ // grunt grenade offset
+ local vector org1 = this.origin +
+ (v_forward * 30 + v_right * 5 + '0 0 16');
if (this.spawnflags & I_AM_TURRET)
- PreachFireGrenade (this.attack_elevation);
+ fire_grenade (org1, 40, 40, attack_elevation);
else
- GruntFireGrenade ();
+ fire_grenade (org1, 40, 40, 0);
}
else if (this.style == 3)
{
+ // Enforcer Laser
ai_face ();
- genforcer_fire ();
+ makevectors (this.angles);
+ fire_laser (this.origin +
+ (v_forward * 30 + v_right * 5 + '0 0 12'),
+ this.enemy.origin - this.origin);
}
else if (this.style == 4 || this.style == 5)
{
+ // Nailgun; MonFireSpike -- used for Grunts
ai_face ();
- MonFireSpike ();
+
+ sound_attack (this, CHAN_WEAPON, "weapons/rocket1i.wav",
+ 1, ATTN_NORM);
+ this.effects = this.effects | EF_MUZZLEFLASH;
+
+ if (this.style == 5)
+ this.attack_finished = time + 1.5;
+ else
+ this.attack_finished = time + 0.2;
+
+ // thanks Voidforce -- dumptruck_ds
+ makevectors (this.angles);
+
+ fire_spike (this.origin +
+ (v_forward * 30 + v_right * 5 + '0 0 12'),
+ this.enemy.origin - this.origin,
+ SPIKE_SUPER_DAMAGE, SPIKE_SPEED);
}
else
{
- */
local vector dir;
local entity en;
ai_face ();
+ this.effects |= EF_MUZZLEFLASH;
sound_attack (this, CHAN_WEAPON, "soldier/sattck1.wav",
1, ATTN_NORM);
@@ -233,9 +264,7 @@ class monster_army: base_walkmonster
dir = en.origin - en.velocity * 0.2;
dir = normalize (dir - this.origin);
FireBullets (4, dir, '0.1 0.1 0');
- /*
}
- */
};
//--------------------------------------------------------------
@@ -281,7 +310,7 @@ class monster_army: base_walkmonster
};
//--------------------------------------------------------------
- nonvirtual void() do_destroy =
+ virtual void() do_destroy =
{
// check for gib
if (this.health < -35)
@@ -429,7 +458,6 @@ class monster_army: base_walkmonster
}
ai_face ();
army_fire ();
- this.effects = this.effects | EF_MUZZLEFLASH;
};
nonvirtual void() atk6 = [$shoot6, atk7] { ai_face (); };
nonvirtual void() atk7 = [$shoot7, atk8]
@@ -443,31 +471,31 @@ class monster_army: base_walkmonster
//--------------------------------------------------------------
// Grunt turrent attack functions
//--------------------------------------------------------------
- nonvirtual void() turret_atk1 = [$shoot1, turret_atk2]
+ nonvirtual void() tur_atk1 = [$shoot1, tur_atk2]
{
ai_face ();
this.count = 0;
this.t_length = 4 + floor (random() * 4);
};
- nonvirtual void() turret_atk2 = [$shoot2, turret_atk3]
+ nonvirtual void() tur_atk2 = [$shoot2, tur_atk3]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
OGRE_DEFAULT_ELEVATION, this.origin, this.enemy.origin);
};
- nonvirtual void() turret_atk3 = [$shoot3, turret_atk4]
+ nonvirtual void() tur_atk3 = [$shoot3, tur_atk4]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
this.attack_elevation, this.origin, this.enemy.origin);
};
- nonvirtual void() turret_atk4 = [$shoot4, turret_atk5]
+ nonvirtual void() tur_atk4 = [$shoot4, tur_atk5]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
this.attack_elevation, this.origin, this.enemy.origin);
};
- nonvirtual void() turret_atk5 =
+ nonvirtual void() tur_atk5 =
{
this.frame = $shoot5;
this.nextthink = time + .1;
@@ -477,24 +505,23 @@ class monster_army: base_walkmonster
}
else
{
- this.think = turret_atk6;
+ this.think = tur_atk6;
}
ai_face ();
army_fire ();
- this.effects = this.effects | EF_MUZZLEFLASH;
};
- nonvirtual void() turret_atk6 = [$shoot6, turret_atk7] { ai_face (); };
- nonvirtual void() turret_atk7 = [$shoot7, turret_atk8]
+ nonvirtual void() tur_atk6 = [$shoot6, tur_atk7] { ai_face (); };
+ nonvirtual void() tur_atk7 = [$shoot7, tur_atk8]
{
ai_face ();
- sub_checkrefire (turret_atk1);
+ sub_checkrefire (tur_atk1);
};
- nonvirtual void() turret_atk8 = [$shoot8, turret_atk9] { ai_face (); };
- nonvirtual void() turret_atk9 = [$stand4, turret_atk10]
+ nonvirtual void() tur_atk8 = [$shoot8, tur_atk9] { ai_face (); };
+ nonvirtual void() tur_atk9 = [$stand4, tur_atk10]
{
ai_face ();
};
- nonvirtual void() turret_atk10 = [$stand5, seek_stand1]
+ nonvirtual void() tur_atk10 = [$stand5, seek_stand1]
{
ai_face ();
};
@@ -705,7 +732,7 @@ class monster_army: base_walkmonster
else
this.think_run = this.run1;
this.think_missile = this.atk1;
- this.think_turret = this.turret_atk1;
+ this.think_turret = this.tur_atk1;
if !(this.berserk)
// Berserk test from
@@ -728,132 +755,6 @@ class monster_army: base_walkmonster
};
};
-/*
-//----------------------------------------------------------------------
-// SOLDIER CODE
-//----------------------------------------------------------------------
-void() genforcer_fire =
-{
- local vector org;
-
- // redundant -- dumptruck_ds
- // self.effects = self.effects | EF_MUZZLEFLASH;
- makevectors (self.angles);
-
- org = self.origin + v_forward * 30 + v_right * 5 + '0 0 12';
-
- LaunchLaser (org, self.enemy.origin - self.origin);
-};
-
-//----------------------------------------------------------------------
-// GruntFireGrenade
-//----------------------------------------------------------------------
-void() GruntFireGrenade =
-{
- local entity missile;
-
- // redundant -- dumptruck_ds
- // self.effects = self.effects | EF_MUZZLEFLASH;
-
- sound_attack (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_BBOX;
-
- // set missile speed
- makevectors (self.angles);
-
- missile.velocity = normalize (self.enemy.origin - self.origin);
- missile.velocity = missile.velocity * 600;
- missile.velocity_z = 200;
- missile.avelocity = '300 300 300';
- missile.angles = vectoangles(missile.velocity);
- missile.touch = OgreGrenadeTouch;
-
- // set missile duration
- missile.nextthink = time + 2.5;
- missile.think = OgreGrenadeExplode;
- // setmodel (missile, "progs/grenade.mdl");
-
- // dumptruck_ds
- if (self.mdl_proj != "")
- {
- setmodel (missile, self.mdl_proj);
- }
- else
- {
- setmodel (missile, "progs/grenade.mdl");
- }
-
- // dumptruck_ds
- if (!missile.skin_proj)
- {
- missile.skin = self.skin_proj;
- }
- else
- {
- missile.skin = 0;
- }
-
- setsize (missile, '0 0 0', '0 0 0');
- // dumptruck_ds
- setorigin (missile, self.origin + v_forward * 30 +
- v_right * 5 + '0 0 16');
-};
-
-//----------------------------------------------------------------------
-// MonFireSpike -- used for Grunts
-//----------------------------------------------------------------------
-void() MonFireSpike =
-{
- local vector dir;
- // local entity old;
-
- sound_attack (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
- if (self.style == 5)
- self.attack_finished = time + 1.5;
- else
- self.attack_finished = time + 0.2;
-
- dir = normalize (self.enemy.origin - self.origin);
- // thanks Voidforce -- dumptruck_ds
- makevectors (self.angles);
-
- //dumptruck_ds
- launch_spike (self.origin + v_forward * 30 +
- v_right * 5 + '0 0 12', dir);
- // launch_spike (self.origin + '0 0 16', dir);
-
- // newmis.touch = superspike_touch;
- // setmodel (newmis, "progs/s_spike.mdl");
-
- // dumptruck_ds
- if (self.mdl_proj != "")
- {
- setmodel (newmis, self.mdl_proj);
- }
- else
- {
- setmodel (newmis, "progs/s_spike.mdl");
- }
-
- // dumptruck_ds
- if (!newmis.skin_proj)
- {
- newmis.skin = self.skin_proj;
- }
- else
- {
- newmis.skin = 0;
- }
- // dumptruck_ds - end
-
- setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
-};
-*/
-
/* Scenic Dead Monster Patch stuff here from DeadStuff mod -- dumptruck_ds */
/*QUAKED monster_dead_army (0 0.5 0.8) (-16 -16 -24) (16 16 32) SOLID FACE_UP X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
Return to the top of this page or return to the overview of this repo.
Diff qc/monsters/wizard.qc
diff --git a/qc/monsters/wizard.qc b/qc/monsters/wizard.qc
index f5ab77e..1127450 100644
--- a/qc/monsters/wizard.qc
+++ b/qc/monsters/wizard.qc
@@ -23,70 +23,6 @@ $frame pain1 pain2 pain3 pain4
$frame death1 death2 death3 death4 death5 death6 death7 death8
-// Next two comments are strays preserved for reference purposes -- CEV
-
-//======================================================================
-// 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.
-//======================================================================
-
-//======================================================================
-// FAST ATTACKS
-//======================================================================
-
-//----------------------------------------------------------------------
-// Wizard missile think function
-// TODO CEV: rework into a proper projectile
-//----------------------------------------------------------------------
-void() Wiz_FastFire =
-{
- local vector vec;
- local vector dst;
- local entity oldself;
- local float projspeed = self.owner.proj_speed_mod * 600;
-
- 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_attack (self, CHAN_WEAPON, "wizard/wattack.wav",
- // 1, ATTN_NORM);
- launch_spike (self.origin, vec);
- SetSpeed (newmis, vec, projspeed);
- newmis.owner = self.owner;
- newmis.classname = "wizspike";
-
- if (self.owner.projexpl)
- {
- // dprint ("spawning exploding wizard proj "
- // "from fastfire\n");
- newmis.touch = T_WizardMisTouch;
- }
-
- if (self.owner.homing)
- {
- oldself = self;
- self = self.owner;
- SetupHoming (newmis, projspeed);
- self = oldself;
- }
-
- setmodel (newmis, self.owner.mdl_proj);
- newmis.skin = self.owner.skin_proj;
- setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
-
- }
-
- remove (self);
-};
-
/*QUAKED monster_wizard (1 0 0) (-16 -16 -24) (16 16 40) AMBUSH X X TRIGGER_SPAWNED X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
{
model ("progs/wizard.mdl");
@@ -151,39 +87,9 @@ damage_mod(float) : "USE WITH CAUTION! Multiply all damage from this monster by
*/
class monster_wizard: base_flymonster
{
- //--------------------------------------------------------------
- // Wiz_StartFast -- TODO CEV rework into a new projectile class
- //--------------------------------------------------------------
- nonvirtual void() startfast =
+ nonvirtual void() attack_ranged =
{
- local entity missile;
-
- // sound_attack (this, CHAN_WEAPON, "wizard/wattack.wav",
- // 1, ATTN_NORM);
- this.v_angle = this.angles;
- makevectors (this.angles);
-
- missile = spawn ();
- missile.owner = this;
- missile.nextthink = time + 0.6;
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, this.origin + '0 0 30' +
- v_forward * 14 + v_right * 14);
- missile.enemy = this.enemy;
- missile.nextthink = time + 0.8;
- missile.think = Wiz_FastFire;
- missile.movedir = v_right;
-
- missile = spawn ();
- missile.owner = this;
- missile.nextthink = time + 1;
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, this.origin + '0 0 30' +
- v_forward * 14 + v_right * -14);
- missile.enemy = this.enemy;
- missile.nextthink = time + 0.3;
- missile.think = Wiz_FastFire;
- missile.movedir = VEC_ORIGIN - v_right;
+ fire_wizardspell ();
};
//--------------------------------------------------------------
@@ -213,7 +119,7 @@ class monster_wizard: base_flymonster
//--------------------------------------------------------------
// Wiz_AttackSound
//--------------------------------------------------------------
- nonvirtual void() attacksound =
+ nonvirtual void() attack_sound =
{
// this is a hack to fix Wizard custom attack sounds
sound_attack (this, CHAN_AUTO, "wizard/wattack.wav",
@@ -241,12 +147,6 @@ class monster_wizard: base_flymonster
};
//--------------------------------------------------------------
- nonvirtual void() wiz_missile =
- {
- this.fast1();
- };
-
- //--------------------------------------------------------------
// WizardCheckAttack
//--------------------------------------------------------------
virtual float() ai_checkattack =
@@ -395,8 +295,8 @@ class monster_wizard: base_flymonster
nonvirtual void() fast1 = [$magatt1, fast2]
{
ai_face ();
- this.startfast ();
- this.attacksound ();
+ this.attack_ranged ();
+ this.attack_sound ();
};
nonvirtual void() fast2 = [$magatt2, fast3] { ai_face (); };
nonvirtual void() fast3 = [$magatt3, fast4] { ai_face (); };
@@ -406,7 +306,7 @@ class monster_wizard: base_flymonster
nonvirtual void() fast7 = [$magatt5, fast8]
{
ai_face ();
- this.attacksound ();
+ this.attack_sound ();
};
nonvirtual void() fast8 = [$magatt4, fast9] { ai_face (); };
nonvirtual void() fast9 = [$magatt3, fast10] { ai_face (); };
@@ -581,12 +481,12 @@ class monster_wizard: base_flymonster
this.think_stand = this.stand1;
this.think_walk = this.walk1;
this.think_run = this.run1;
- this.think_missile = this.wiz_missile;
+ this.think_missile = this.fast1;
// Berserk test from
// http://celephais.net/board/view_thread.php?id=4&start=3465
// -- dumptruck_ds
if !(this.berserk)
- this.th_pain = do_damage;
+ this.th_pain = this.do_damage;
else
this.th_pain = sub_nullpain;
this.th_die = do_destroy;
Return to the top of this page or return to the overview of this repo.
Diff qc/monsters/zombie.qc
diff --git a/qc/monsters/zombie.qc b/qc/monsters/zombie.qc
index 51b4a75..cef31db 100644
--- a/qc/monsters/zombie.qc
+++ b/qc/monsters/zombie.qc
@@ -142,62 +142,6 @@ class monster_zombie: base_walkmonster
};
//--------------------------------------------------------------
- // PreachFireZombie -- for Z-Aware Zombies in Turret Mode only
- //--------------------------------------------------------------
- nonvirtual void(float elevation) fire_preach =
- {
- local entity missile;
- local vector ang;
-
- // this.effects = this.effects | EF_MUZZLEFLASH;
-
- sound_attack (this, CHAN_WEAPON, "zombie/z_shot1.wav",
- 1, ATTN_NORM);
-
- missile = spawn ();
- missile.owner = this;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_BBOX;
-
- // set missile speed
- ang = this.angles;
- ang_x = -elevation;
- makevectors (ang);
-
- missile.velocity = v_forward * OGRE_G_VEL;
- missile.avelocity = '3000 1000 2000';
- missile.angles = vectoangles(missile.velocity);
- missile.touch = ZombieGrenadeTouch;
-
- // set missile duration
- missile.nextthink = time + 2.5;
- missile.think = sub_remove;
- // setmodel (missile, "progs/grenade.mdl");
- // dumptruck_ds
- if (this.mdl_proj != "")
- {
- setmodel (missile, this.mdl_proj);
- }
- else
- {
- setmodel (missile, "progs/zom_gib.mdl");
- }
-
- // dumptruck_ds
- if (!missile.skin_proj)
- {
- missile.skin = this.skin_proj;
- }
- else
- {
- missile.skin = 0;
- }
-
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, this.origin);
- };
-
- //--------------------------------------------------------------
nonvirtual void() fire_missile =
{
local float r;
@@ -220,69 +164,11 @@ class monster_zombie: base_walkmonster
r = random ();
if (r < 0.3)
- this.turret_attb1 ();
+ this.tur_atkb1 ();
else if (r < 0.6)
- this.turret_atta1 ();
+ this.tur_atka1 ();
else
- this.turret_attc1 ();
- };
-
- //--------------------------------------------------------------
- // ZombieFireGrenade
- //--------------------------------------------------------------
- nonvirtual void(vector st) fire_grenade =
- {
- local entity nade;
- local vector org;
-
- sound_attack (this, CHAN_WEAPON, "zombie/z_shot1.wav",
- 1, ATTN_NORM);
-
- nade = spawn ();
- nade.owner = this;
- nade.movetype = MOVETYPE_BOUNCE;
- nade.solid = SOLID_BBOX;
-
- // calc org
- org = this.origin + st_x * v_forward +
- st_y * v_right +
- (st_z - 24) * v_up;
-
- // set missile speed
- makevectors (this.angles);
- nade.velocity = normalize (this.enemy.origin - org);
- nade.velocity = nade.velocity * 600;
- nade.velocity_z = 200;
- nade.avelocity = '3000 1000 2000';
- nade.touch = ZombieGrenadeTouch;
-
- // set missile duration
- nade.nextthink = time + 2.5;
- nade.think = sub_remove;
-
- // setmodel (nade, "progs/zom_gib.mdl");
- // dumptruck_ds custom_mdls
- if (this.mdl_proj != "")
- {
- setmodel (nade, this.mdl_proj);
- }
- else
- {
- setmodel (nade, "progs/zom_gib.mdl");
- }
-
- // dumptruck_ds
- if (!nade.skin_proj)
- {
- nade.skin = this.skin_proj;
- }
- else
- {
- nade.skin = 0;
- }
-
- setsize (nade, '0 0 0', '0 0 0');
- setorigin (nade, org);
+ this.tur_atkc1 ();
};
//--------------------------------------------------------------
@@ -459,7 +345,7 @@ class monster_zombie: base_walkmonster
nonvirtual void() atta13 = [$atta13, run1]
{
ai_face ();
- this.fire_grenade ('-10 -22 30');
+ fire_zombiechunk ('-10 -22 30', 0);
};
//--------------------------------------------------------------
@@ -481,7 +367,7 @@ class monster_zombie: base_walkmonster
nonvirtual void() attb14 = [$attb13, run1]
{
ai_face ();
- this.fire_grenade ('-10 -24 29');
+ fire_zombiechunk ('-10 -24 29', 0);
};
//--------------------------------------------------------------
@@ -501,7 +387,7 @@ class monster_zombie: base_walkmonster
nonvirtual void() attc12 = [$attc12, run1]
{
ai_face ();
- this.fire_grenade ('-12 -19 29');
+ fire_zombiechunk ('-12 -19 29', 0);
};
///////////////////////////
@@ -511,121 +397,121 @@ class monster_zombie: base_walkmonster
//--------------------------------------------------------------
// Zombie Turret Attack A
//--------------------------------------------------------------
- nonvirtual void() turret_atta1 = [$atta1, turret_atta2]
+ nonvirtual void() tur_atka1 = [$atta1, tur_atka2]
{
this.health = 60;
ai_face ();
};
- nonvirtual void() turret_atta2 = [$atta2, turret_atta3] { ai_face (); };
- nonvirtual void() turret_atta3 = [$atta3, turret_atta4] { ai_face (); };
- nonvirtual void() turret_atta4 = [$atta4, turret_atta5] { ai_face (); };
- nonvirtual void() turret_atta5 = [$atta5, turret_atta6] { ai_face (); };
- nonvirtual void() turret_atta6 = [$atta6, turret_atta7] { ai_face (); };
- nonvirtual void() turret_atta7 = [$atta7, turret_atta8] { ai_face (); };
- nonvirtual void() turret_atta8 = [$atta8, turret_atta9] { ai_face (); };
- nonvirtual void() turret_atta9 = [$atta9, turret_atta10] { ai_face ();};
- nonvirtual void() turret_atta10 = [$atta10, turret_atta11]
+ nonvirtual void() tur_atka2 = [$atta2, tur_atka3] { ai_face (); };
+ nonvirtual void() tur_atka3 = [$atta3, tur_atka4] { ai_face (); };
+ nonvirtual void() tur_atka4 = [$atta4, tur_atka5] { ai_face (); };
+ nonvirtual void() tur_atka5 = [$atta5, tur_atka6] { ai_face (); };
+ nonvirtual void() tur_atka6 = [$atta6, tur_atka7] { ai_face (); };
+ nonvirtual void() tur_atka7 = [$atta7, tur_atka8] { ai_face (); };
+ nonvirtual void() tur_atka8 = [$atta8, tur_atka9] { ai_face (); };
+ nonvirtual void() tur_atka9 = [$atta9, tur_atka10] { ai_face ();};
+ nonvirtual void() tur_atka10 = [$atta10, tur_atka11]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
OGRE_DEFAULT_ELEVATION, this.origin, this.enemy.origin);
};
- nonvirtual void() turret_atta11 = [$atta11, turret_atta12]
+ nonvirtual void() tur_atka11 = [$atta11, tur_atka12]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
this.attack_elevation, this.origin, this.enemy.origin);
};
- nonvirtual void() turret_atta12 = [$atta12, turret_atta13]
+ nonvirtual void() tur_atka12 = [$atta12, tur_atka13]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
this.attack_elevation, this.origin, this.enemy.origin);
};
- nonvirtual void() turret_atta13 = [$atta13, alt_seek1]
+ nonvirtual void() tur_atka13 = [$atta13, alt_seek1]
{
ai_run (0);
- fire_preach (this.attack_elevation);
+ fire_zombiechunk ('0 0 0', this.attack_elevation);
};
//--------------------------------------------------------------
// Zombie Turret Attack B
//--------------------------------------------------------------
- nonvirtual void() turret_attb1 = [$attb1, turret_attb2]
+ nonvirtual void() tur_atkb1 = [$attb1, tur_atkb2]
{
this.health = 60;
ai_face ();
};
- nonvirtual void() turret_attb2 = [$attb2, turret_attb3] { ai_face (); };
- nonvirtual void() turret_attb3 = [$attb3, turret_attb4] { ai_face (); };
- nonvirtual void() turret_attb4 = [$attb4, turret_attb5] { ai_face (); };
- nonvirtual void() turret_attb5 = [$attb5, turret_attb6] { ai_face (); };
- nonvirtual void() turret_attb6 = [$attb6, turret_attb7] { ai_face (); };
- nonvirtual void() turret_attb7 = [$attb7, turret_attb8] { ai_face (); };
- nonvirtual void() turret_attb8 = [$attb8, turret_attb9] { ai_face (); };
- nonvirtual void() turret_attb9 = [$attb9, turret_attb10] { ai_face ();};
- nonvirtual void() turret_attb10 = [$attb10, turret_attb11] {ai_face();};
- nonvirtual void() turret_attb11 = [$attb11, turret_attb12]
+ nonvirtual void() tur_atkb2 = [$attb2, tur_atkb3] { ai_face (); };
+ nonvirtual void() tur_atkb3 = [$attb3, tur_atkb4] { ai_face (); };
+ nonvirtual void() tur_atkb4 = [$attb4, tur_atkb5] { ai_face (); };
+ nonvirtual void() tur_atkb5 = [$attb5, tur_atkb6] { ai_face (); };
+ nonvirtual void() tur_atkb6 = [$attb6, tur_atkb7] { ai_face (); };
+ nonvirtual void() tur_atkb7 = [$attb7, tur_atkb8] { ai_face (); };
+ nonvirtual void() tur_atkb8 = [$attb8, tur_atkb9] { ai_face (); };
+ nonvirtual void() tur_atkb9 = [$attb9, tur_atkb10] { ai_face ();};
+ nonvirtual void() tur_atkb10 = [$attb10, tur_atkb11] {ai_face();};
+ nonvirtual void() tur_atkb11 = [$attb11, tur_atkb12]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
OGRE_DEFAULT_ELEVATION, this.origin, this.enemy.origin);
};
- nonvirtual void() turret_attb12 = [$attb12, turret_attb13]
+ nonvirtual void() tur_atkb12 = [$attb12, tur_atkb13]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
this.attack_elevation, this.origin, this.enemy.origin);
};
- nonvirtual void() turret_attb13 = [$attb13, turret_attb14]
+ nonvirtual void() tur_atkb13 = [$attb13, tur_atkb14]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
this.attack_elevation, this.origin, this.enemy.origin);
};
- nonvirtual void() turret_attb14 = [$attb13, alt_seek1]
+ nonvirtual void() tur_atkb14 = [$attb13, alt_seek1]
{
ai_run (0);
- fire_preach (this.attack_elevation);
+ fire_zombiechunk ('0 0 0', this.attack_elevation);
};
//--------------------------------------------------------------
// Zombie Turret Attack C
//--------------------------------------------------------------
- nonvirtual void() turret_attc1 = [$attc1, turret_attc2]
+ nonvirtual void() tur_atkc1 = [$attc1, tur_atkc2]
{
this.health = 60;
ai_face ();
};
- nonvirtual void() turret_attc2 = [$attc2, turret_attc3] { ai_face (); };
- nonvirtual void() turret_attc3 = [$attc3, turret_attc4] { ai_face (); };
- nonvirtual void() turret_attc4 = [$attc4, turret_attc5] { ai_face (); };
- nonvirtual void() turret_attc5 = [$attc5, turret_attc6] { ai_face (); };
- nonvirtual void() turret_attc6 = [$attc6, turret_attc7] { ai_face (); };
- nonvirtual void() turret_attc7 = [$attc7, turret_attc8] { ai_face (); };
- nonvirtual void() turret_attc8 = [$attc8, turret_attc9] { ai_face (); };
- nonvirtual void() turret_attc9 = [$attc9, turret_attc10]
+ nonvirtual void() tur_atkc2 = [$attc2, tur_atkc3] { ai_face (); };
+ nonvirtual void() tur_atkc3 = [$attc3, tur_atkc4] { ai_face (); };
+ nonvirtual void() tur_atkc4 = [$attc4, tur_atkc5] { ai_face (); };
+ nonvirtual void() tur_atkc5 = [$attc5, tur_atkc6] { ai_face (); };
+ nonvirtual void() tur_atkc6 = [$attc6, tur_atkc7] { ai_face (); };
+ nonvirtual void() tur_atkc7 = [$attc7, tur_atkc8] { ai_face (); };
+ nonvirtual void() tur_atkc8 = [$attc8, tur_atkc9] { ai_face (); };
+ nonvirtual void() tur_atkc9 = [$attc9, tur_atkc10]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
OGRE_DEFAULT_ELEVATION, this.origin, this.enemy.origin);
};
- nonvirtual void() turret_attc10 = [$attc10, turret_attc11]
+ nonvirtual void() tur_atkc10 = [$attc10, tur_atkc11]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
this.attack_elevation, this.origin, this.enemy.origin);
};
- nonvirtual void() turret_attc11 = [$attc11, turret_attc12]
+ nonvirtual void() tur_atkc11 = [$attc11, tur_atkc12]
{
ai_face ();
- this.attack_elevation = IterateElevation (
+ this.attack_elevation = preach_iterate_elevation (
this.attack_elevation, this.origin, this.enemy.origin);
};
- nonvirtual void() turret_attc12 = [$attc12, alt_seek1]
+ nonvirtual void() tur_atkc12 = [$attc12, alt_seek1]
{
ai_run (0);
- fire_preach (this.attack_elevation);
+ fire_zombiechunk ('0 0 0', this.attack_elevation);
};
//--------------------------------------------------------------
@@ -770,7 +656,7 @@ class monster_zombie: base_walkmonster
// Chainsaw will gib zombie
if (this.axhitme == 2)
{
- T_Damage (this, world, world, 80);
+ this.t_damage2 (this, world, world, 80);
return;
}
sound_pain (this, CHAN_VOICE, "zombie/z_pain.wav",
Return to the top of this page or return to the overview of this repo.
Diff qc/obituary.qc
diff --git a/qc/obituary.qc b/qc/obituary.qc
new file mode 100644
index 0000000..4dfdcd1
--- /dev/null
+++ b/qc/obituary.qc
@@ -0,0 +1,336 @@
+//==============================================================================
+// obituary.qc
+//==============================================================================
+
+//----------------------------------------------------------------------
+// ClientObituary -- called when a player dies
+//----------------------------------------------------------------------
+void(entity targ, entity inflictor, entity attacker) ClientObituary =
+{
+ local float rnum;
+ local string deathstring, deathstring2;
+
+ rnum = random ();
+ deathstring = deathstring2 = "";
+
+ // refactored to remove one level of indentation -- CEV
+ if (targ.classname != "player")
+ return;
+
+ 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;
+ }
+
+ if (attacker.classname == "teledeath2")
+ {
+ bprint ("Satan's power deflects ");
+ bprint (targ.netname);
+ bprint ("'s telefrag\n");
+
+ targ.frags = targ.frags - 1;
+ return;
+ }
+
+ // 1998-07-26 Pentagram telefrag fix by Zoid/Maddes start
+ // double 666 telefrag
+ // (can happen often in deathmatch 4 and levels with more
+ // than one pentagram)
+ if (attacker.classname == "teledeath3")
+ {
+ bprint (targ.netname);
+ bprint (" was telefragged by ");
+ bprint (attacker.owner.netname);
+ bprint ("'s Satan's power\n");
+ // 1998-07-26 only tfrag player on spot by Maddes start
+ // targ.frags = targ.frags - 1;
+ attacker.owner.frags = attacker.owner.frags + 1;
+ // 1998-07-26 only tfrag player on spot by Maddes end
+ return;
+ }
+
+ // 1998-07-26 Pentagram telefrag fix by Zoid/Maddes end
+ if (attacker.classname == "player")
+ {
+ if (targ == attacker)
+ {
+ // killed self
+ attacker.frags = attacker.frags - 1;
+ bprint (targ.netname);
+
+ if (targ.weapon == 64 &&
+ targ.waterlevel > WATERLEVEL_FEET)
+ {
+ bprint (" discharges into the water.\n");
+ return;
+ }
+ if (targ.weapon == IT_GRENADE_LAUNCHER)
+ bprint (" tries to put the pin back in\n");
+ else
+ bprint (" becomes bored with life\n");
+ return;
+ }
+ else if ((teamplay == 2) && (targ.team > 0) &&
+ (targ.team == attacker.team))
+ {
+ 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 (attacker.netname);
+ 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 > WATERLEVEL_FEET)
+ 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);
+
+ // custom obituary messages
+ if (inflictor.deathtype != "")
+ {
+ bprint (" ");
+ bprint (inflictor.deathtype);
+ bprint ("\n");
+ return;
+ }
+ if (attacker.deathtype != "")
+ {
+ bprint (" ");
+ bprint (attacker.deathtype);
+ bprint ("\n");
+ return;
+ }
+
+ // killed by a monster?
+ // if (attacker.flags & FL_MONSTER)
+ if ((attacker.flags & FL_MONSTER) && (attacker.obit_name == ""))
+ {
+ if (attacker.classname == "monster_army")
+ bprint (" was shot by a Grunt\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_dragon")
+ bprint (" was fried by a Dragon\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_ogre_marksman")
+ // dumptruck_ds
+ bprint (" was felled by a Marksman\n");
+ if (attacker.classname == "monster_oldone")
+ bprint (" became one with Shub-Niggurath\n");
+ if (attacker.classname == "monster_oldone2")
+ // dumptruck_ds
+ bprint (" became one with Shub-Niggurath\n");
+ if (attacker.classname == "monster_boss2")
+ // dumptruck_ds
+ bprint (" was exploded by Chthon\n");
+ if (attacker.classname == "monster_boss")
+ // dumptruck_ds
+ bprint (" was exploded by Chthon\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_vomit")
+ bprint (" was vomited on by a Vomitus\n");
+ if (attacker.classname == "monster_wizard")
+ bprint (" was scragged by a Scrag\n");
+ if (attacker.classname == "monster_zombie")
+ bprint (" joins the Zombies\n");
+
+ return;
+ }
+
+ // obits for custom monsters -- progs_dump -- dumptruck_ds
+ if (attacker.obit_name != "")
+ {
+ bprint (" was ");
+ if !(attacker.obit_method)
+ bprint ("killed");
+ else
+ // e.g. ripped apart
+ bprint (attacker.obit_method);
+ bprint (" by ");
+ // a bad monster
+ bprint (attacker.obit_name);
+ bprint ("\n");
+ return;
+ }
+
+ // tricks and traps
+ if (attacker.classname == "explo_box" ||
+ attacker.classname == "play_explosion")
+ {
+ bprint (" blew up\n");
+ return;
+ }
+ if (attacker.classname == "func_laser")
+ {
+ bprint (" discovered that lasers are hot\n");
+ return;
+ }
+ if ((attacker.solid == SOLID_BSP &&
+ attacker != world &&
+ attacker.classname != "togglewall") ||
+ (inflictor.classname == "func_movewall" &&
+ !(inflictor.spawnflags & MOVEWALL_TOUCH)))
+ {
+ bprint (" was squished\n");
+ return;
+ }
+ if (attacker.classname == "trap_shooter" ||
+ attacker.classname == "trap_spikeshooter" ||
+ attacker.classname == "trap_switched_shooter")
+ {
+ // bprint (" was spiked\n");
+ // changed for custom shooters -- dumptruck_ds
+ bprint (" was unlucky\n");
+ return;
+ }
+ if (attacker.classname == "ltrail_start" ||
+ attacker.classname == "ltrail_relay")
+ {
+ bprint (" had an electrifying experience\n");
+ return;
+ }
+ if (attacker.classname == "fireball")
+ {
+ bprint (" ate a lavaball\n");
+ return;
+ }
+ if (attacker.classname == "trigger_changelevel")
+ {
+ bprint (" tried to leave\n");
+ return;
+ }
+
+ // in-liquid deaths
+ if (targ.deathtype == "drowning")
+ {
+ if (random() < 0.5)
+ bprint (" sleeps with the fishes\n");
+ else
+ bprint (" sucks it down\n");
+ return;
+ }
+ if (targ.deathtype == "slime")
+ {
+ if (random() < 0.5)
+ bprint (" gulped a load of slime\n");
+ else
+ bprint (" can't exist on slime alone\n");
+ return;
+ }
+ if (targ.deathtype == "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")
+ {
+ bprint (" fell to his death\n");
+ return;
+ }
+
+ // hell if I know; he's just dead!!!
+ bprint (" died\n");
+ }
+};
Return to the top of this page or return to the overview of this repo.
Diff qc/player/player.qc
diff --git a/qc/player/player.qc b/qc/player/player.qc
deleted file mode 100644
index 22a3aa7..0000000
--- a/qc/player/player.qc
+++ /dev/null
@@ -1,1049 +0,0 @@
-//==============================================================================
-// player
-//==============================================================================
-
-// prototypes
-void(float num_bubbles) PlayerDeathBubbles;
-void() player_run;
-void() player_diea1;
-void() player_dieb1;
-void() player_diec1;
-void() player_died1;
-void() player_diee1;
-void() player_die_ax1;
-
-//======================================================================
-// Player ammo limits, weapon selection
-//======================================================================
-
-//----------------------------------------------------------------------
-// PlayerSetCurrentAmmo -- was W_SetCurrentAmmo in weapons.qc
-//----------------------------------------------------------------------
-void() PlayerSetCurrentAmmo =
-{
- // get out of any weapon firing states
- player_run ();
-
- self.items = self.items - (self.items & (IT_SHELLS | IT_NAILS |
- IT_ROCKETS | IT_CELLS));
-
- if (self.weapon == IT_AXE)
- {
- self.currentammo = 0;
- self.weaponmodel = "progs/v_axe.mdl";
- self.weaponframe = 0;
- }
- else if (self.weapon == IT_SHOTGUN)
- {
- self.currentammo = self.ammo_shells;
- self.weaponmodel = "progs/v_shot.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_SHELLS;
- }
- else if (self.weapon == IT_SUPER_SHOTGUN)
- {
- self.currentammo = self.ammo_shells;
- self.weaponmodel = "progs/v_shot2.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_SHELLS;
- }
- else if (self.weapon == IT_NAILGUN)
- {
- self.currentammo = self.ammo_nails;
- self.weaponmodel = "progs/v_nail.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_NAILS;
- }
- else if (self.weapon == IT_SUPER_NAILGUN)
- {
- self.currentammo = self.ammo_nails;
- self.weaponmodel = "progs/v_nail2.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_NAILS;
- }
- else if (self.weapon == IT_GRENADE_LAUNCHER)
- {
- self.currentammo = self.ammo_rockets;
- self.weaponmodel = "progs/v_rock.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_ROCKETS;
- }
- else if (self.weapon == IT_ROCKET_LAUNCHER)
- {
- self.currentammo = self.ammo_rockets;
- self.weaponmodel = "progs/v_rock2.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_ROCKETS;
- }
- else if (self.weapon == IT_LIGHTNING)
- {
- self.currentammo = self.ammo_cells;
- self.weaponmodel = "progs/v_light.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_CELLS;
- }
- else
- {
- self.currentammo = 0;
- self.weaponmodel = "";
- self.weaponframe = 0;
- }
-};
-
-//----------------------------------------------------------------------
-float() PlayerCheckNoAmmo =
-{
- if (self.currentammo > 0)
- return TRUE;
-
- if (self.weapon == IT_AXE)
- return TRUE;
-
- self.weapon = PlayerBestWeapon ();
-
- PlayerSetCurrentAmmo ();
-
- // drop the weapon down
- return FALSE;
-};
-
-//----------------------------------------------------------------------
-// PlayerBestWeapon -- was W_BestWeapon in weapons.qc
-//----------------------------------------------------------------------
-float() PlayerBestWeapon =
-{
- if (self.waterlevel <= WATERLEVEL_FEET && self.ammo_cells >= 1 &&
- (self.items & IT_LIGHTNING))
- {
- return IT_LIGHTNING;
- }
-
- if (self.ammo_nails >= 2 && (self.items & IT_SUPER_NAILGUN))
- return IT_SUPER_NAILGUN;
-
- if (self.ammo_shells >= 2 && (self.items & IT_SUPER_SHOTGUN))
- return IT_SUPER_SHOTGUN;
-
- if (self.ammo_nails >= 1 && (self.items & IT_NAILGUN))
- return IT_NAILGUN;
-
- if (self.ammo_shells >= 1 && (self.items & IT_SHOTGUN))
- return IT_SHOTGUN;
-
- return IT_AXE;
-};
-
-//======================================================================
-// Player thinking
-//======================================================================
-
-//----------------------------------------------------------------------
-// PlayerAttack -- An attack impulse can be triggered now
-//----------------------------------------------------------------------
-void() PlayerAttack =
-{
- local float r;
-
- if (!PlayerCheckNoAmmo())
- return;
-
- // calculate forward angle for velocity
- makevectors (self.v_angle);
- // wake monsters up
- self.show_hostile = time + 1;
-
- if (self.weapon == IT_AXE)
- {
- sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
- 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_nail1 ();
- }
- else if (self.weapon == IT_SUPER_NAILGUN)
- {
- player_nail1 ();
- }
- 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)
- {
- player_light1 ();
- self.attack_finished = time + 0.1;
- sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
- }
-};
-
-//======================================================================
-// Player Frame Macros
-//======================================================================
-$cd id1/models/player_4
-$origin 0 -6 24
-$base base
-$skin skin
-
-//----------------------------------------------------------------------
-// running
-$frame axrun1 axrun2 axrun3 axrun4 axrun5 axrun6
-$frame rockrun1 rockrun2 rockrun3 rockrun4 rockrun5 rockrun6
-
-//----------------------------------------------------------------------
-// standing
-$frame stand1 stand2 stand3 stand4 stand5
-$frame axstnd1 axstnd2 axstnd3 axstnd4 axstnd5 axstnd6
-$frame axstnd7 axstnd8 axstnd9 axstnd10 axstnd11 axstnd12
-
-//----------------------------------------------------------------------
-// pain
-$frame axpain1 axpain2 axpain3 axpain4 axpain5 axpain6
-$frame pain1 pain2 pain3 pain4 pain5 pain6
-
-//----------------------------------------------------------------------
-// death
-$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
-
-//----------------------------------------------------------------------
-// attacks
-$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_stand1 = [$axstnd1, player_stand1]
-{
- self.weaponframe = 0;
- if (self.velocity_x || self.velocity_y)
- {
- self.walkframe = 0;
- 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;
-};
-
-//======================================================================
-
-void() player_run = [$rockrun1, player_run]
-{
- self.weaponframe = 0;
- if (!self.velocity_x && !self.velocity_y)
- {
- self.walkframe = 0;
- player_stand1 ();
- 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 = self.frame + self.walkframe;
- }
- self.walkframe = self.walkframe + 1;
-};
-
-//======================================================================
-
-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; };
-
-//======================================================================
-
-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_nail1 = [$nailatt1, player_nail2]
-{
- self.effects = self.effects | EF_MUZZLEFLASH;
-
- if (!self.button0)
- {
- player_run ();
- return;
- }
-
- self.weaponframe = self.weaponframe + 1;
- if (self.weaponframe == 9)
- self.weaponframe = 1;
- SuperDamageSound ();
- W_FireSpikes (4);
- self.attack_finished = time + 0.2;
-};
-
-void() player_nail2 = [$nailatt2, player_nail1]
-{
- self.effects = self.effects | EF_MUZZLEFLASH;
-
- if (!self.button0)
- {
- player_run ();
- return;
- }
-
- self.weaponframe = self.weaponframe + 1;
- if (self.weaponframe == 9)
- self.weaponframe = 1;
- SuperDamageSound ();
- W_FireSpikes (-4);
- self.attack_finished = time + 0.2;
-};
-
-//======================================================================
-
-void() player_light1 = [$light1, player_light2]
-{
- self.effects = self.effects | EF_MUZZLEFLASH;
-
- if (!self.button0)
- {
- player_run ();
- return;
- }
-
- self.weaponframe = self.weaponframe + 1;
- if (self.weaponframe == 5)
- self.weaponframe = 1;
- SuperDamageSound ();
- W_FireLightning ();
- self.attack_finished = time + 0.2;
-};
-
-void() player_light2 = [$light2, player_light1]
-{
- self.effects = self.effects | EF_MUZZLEFLASH;
-
- if (!self.button0)
- {
- player_run ();
- return;
- }
-
- self.weaponframe = self.weaponframe + 1;
- if (self.weaponframe == 5)
- self.weaponframe = 1;
- SuperDamageSound ();
- W_FireLightning ();
- self.attack_finished = time + 0.2;
-};
-
-//======================================================================
-
-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; };
-
-//======================================================================
-
-//----------------------------------------------------------------------
-// PlayerPainSound -- was PainSound()
-//----------------------------------------------------------------------
-void() PlayerPainSound =
-{
- local float rs;
-
- if (self.health < 0)
- return;
-
- if (damage_attacker.classname == "teledeath")
- {
- sound (self, CHAN_VOICE, "player/teledth1.wav", 1, ATTN_NONE);
- return;
- }
-
- // water pain sounds
- if (self.watertype == CONTENT_WATER &&
- self.waterlevel == WATERLEVEL_EYES)
- {
- 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;
- }
-
- // slime pain sounds
- if (self.watertype == CONTENT_SLIME)
- {
- // FIX ME put in some steam here
- // 1998-08-10 Player gulps bubbles when hurt in slime
- // by Maddes start
- if (self.waterlevel == WATERLEVEL_EYES)
- PlayerDeathBubbles (1);
- // 1998-08-10 Player gulps bubbles when hurt in slime
- // by Maddes end
- 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)
- {
- self.axhitme = 0;
- return;
- }
-
- // don't make multiple pain sounds right after each other
- self.pain_finished = time + 0.5;
-
- // ax pain sound
- if (self.axhitme == 1)
- {
- self.axhitme = 0;
- sound (self, CHAN_VOICE, "player/axhit1.wav", 1, ATTN_NORM);
- return;
- }
-
- rs = rint ((random() * 5) + 1);
-
- self.noise = "";
- if (rs == 1)
- self.noise = "player/pain1.wav";
- else if (rs == 2)
- self.noise = "player/pain2.wav";
- else if (rs == 3)
- self.noise = "player/pain3.wav";
- else if (rs == 4)
- self.noise = "player/pain4.wav";
- else if (rs == 5)
- self.noise = "player/pain5.wav";
- else
- self.noise = "player/pain6.wav";
-
- sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
- return;
-};
-
-void() player_pain1 = [$pain1, player_pain2]
-{
- PlayerPainSound ();
- self.weaponframe=0;
-};
-
-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]
-{
- PlayerPainSound ();
- self.weaponframe=0;
-};
-
-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] {};
-
-//----------------------------------------------------------------------
-void(entity attacker, float damage) player_pain =
-{
- if (self.weaponframe)
- return;
-
- if (self.invisible_finished > time)
- // eyes don't have pain frames
- return;
-
- if (self.weapon == IT_AXE)
- player_axpain1 ();
- else
- player_pain1 ();
-};
-
-//======================================================================
-
-//----------------------------------------------------------------------
-void() PlayerDeathBubblesSpawn =
-{
- local temp_bubbles bubble;
- if (self.owner.waterlevel != WATERLEVEL_EYES && self.owner.health > 0)
- {
- // 1998-08-14 Improved bubble spawn by Maddes
- // 1998-08-14 Bubblespawner remove fix by Perged start
- // remove bubble spawner
- remove (self);
- // 1998-08-14 Bubblespawner remove fix by Perged end
- return;
- // 1998-08-14 Bubblespawner remove fix by Perged
- }
-
- bubble = spawn (temp_bubbles, origin: self.owner.origin + '0 0 24');
- // 1998-08-14 Improved bubble spawn by Maddes start
- // self.nextthink = time + 0.1;
- self.nextthink = time + 0.01;
- // 1998-08-14 Improved bubble spawn by Maddes end
- self.think = PlayerDeathBubblesSpawn;
- self.air_finished = self.air_finished + 1;
- if (self.air_finished >= self.bubble_count)
- remove (self);
-};
-
-//----------------------------------------------------------------------
-void(float num_bubbles) PlayerDeathBubbles =
-{
- local entity bubble_spawner;
-
- bubble_spawner = spawn ();
- setorigin (bubble_spawner, self.origin);
- bubble_spawner.movetype = MOVETYPE_NONE;
- bubble_spawner.solid = SOLID_NOT;
- // 1998-08-14 Improved bubble spawn by Maddes start
- // bubble_spawner.nextthink = time + 0.1;
- bubble_spawner.nextthink = time + 0.01;
- // 1998-08-14 Improved bubble spawn by Maddes end
- bubble_spawner.think = PlayerDeathBubblesSpawn;
- bubble_spawner.air_finished = 0;
- bubble_spawner.owner = self;
- bubble_spawner.bubble_count = num_bubbles;
- // return; // 1998-08-14 unnecessary by Maddes
-};
-
-//----------------------------------------------------------------------
-void() PlayerDeathSound =
-{
- local float rs;
-
- // water death sounds
- if (self.waterlevel == WATERLEVEL_EYES)
- {
- PlayerDeathBubbles (20);
- sound (self, CHAN_VOICE, "player/h2odeath.wav", 1, ATTN_NONE);
- return;
- }
-
- rs = rint ((random() * 4) + 1);
- if (rs == 1)
- self.noise = "player/death1.wav";
- if (rs == 2)
- self.noise = "player/death2.wav";
- if (rs == 3)
- self.noise = "player/death3.wav";
- if (rs == 4)
- self.noise = "player/death4.wav";
- if (rs == 5)
- self.noise = "player/death5.wav";
-
- sound (self, CHAN_VOICE, self.noise, 1, ATTN_NONE);
- return;
-};
-
-//----------------------------------------------------------------------
-void() PlayerDead =
-{
- self.nextthink = -1;
- // allow respawn after a certain time
- self.deadflag = DEAD_DEAD;
-};
-
-//----------------------------------------------------------------------
-vector(float dm) VelocityForDamage =
-{
- local vector v;
-
- v_x = 100 * crandom ();
- v_y = 100 * crandom ();
- v_z = 200 + 100 * random ();
-
- if (dm > -50)
- {
- // dprint ("level 1\n");
- v = v * 0.7;
- }
- else if (dm > -200)
- {
- // dprint ("level 3\n");
- v = v * 2;
- }
- else
- {
- v = v * 10;
- }
-
- return v;
-};
-
-//----------------------------------------------------------------------
-void(string gibname, float dm) ThrowGib =
-{
- local entity new;
-
- new = spawn ();
- new.origin = self.origin;
- setmodel (new, gibname);
- setsize (new, '0 0 0', '0 0 0');
- new.velocity = VelocityForDamage (dm);
- new.movetype = MOVETYPE_BOUNCE;
- new.solid = SOLID_NOT;
- new.avelocity_x = random() * 600;
- new.avelocity_y = random() * 600;
- new.avelocity_z = random() * 600;
- new.think = sub_remove;
- new.ltime = time;
- new.nextthink = time + 10 + random() * 10;
- new.frame = 0;
- new.flags = 0;
-};
-
-//----------------------------------------------------------------------
-void(string gibname, float dm) ThrowHead =
-{
- setmodel (self, gibname);
-
- // dumptruck_ds custom_mdl changes
- self.skin = self.skin_head;
- if !(self.skin_head)
- self.skin_head = 0;
- // end dumptruck_ds
-
- self.frame = 0;
- self.nextthink = -1;
- self.movetype = MOVETYPE_BOUNCE;
- self.takedamage = DAMAGE_NO;
- self.solid = SOLID_NOT;
- self.view_ofs = '0 0 8';
- setsize (self, '-16 -16 0', '16 16 56');
- self.velocity = VelocityForDamage (dm);
- self.origin_z = self.origin_z - 24;
- self.flags = self.flags - (self.flags & FL_ONGROUND);
- self.avelocity = crandom() * '0 600 0';
-};
-
-//----------------------------------------------------------------------
-void() GibPlayer =
-{
- ThrowHead ("progs/h_player.mdl", self.health);
- ThrowGib ("progs/gib1.mdl", self.health);
- ThrowGib ("progs/gib2.mdl", self.health);
- ThrowGib ("progs/gib3.mdl", self.health);
-
- self.deadflag = DEAD_DEAD;
-
- if (damage_attacker.classname == "teledeath")
- {
- sound (self, CHAN_VOICE, "player/teledth1.wav", 1, ATTN_NONE);
- return;
- }
-
- if (damage_attacker.classname == "teledeath2")
- {
- sound (self, CHAN_VOICE, "player/teledth1.wav", 1, ATTN_NONE);
- return;
- }
-
- if (random() < 0.5)
- sound (self, CHAN_VOICE, "player/gib.wav", 1, ATTN_NONE);
- else
- sound (self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NONE);
-};
-
-//----------------------------------------------------------------------
-void() PlayerDie =
-{
- local float i;
-
- // 1998-07-23 Palette shift when player dies with quad/pentagram fix
- // by Maddes start
- // self.items = self.items - (self.items & IT_INVISIBILITY);
- self.items = self.items - (self.items &
- (IT_INVISIBILITY | IT_INVULNERABILITY | IT_SUIT | IT_QUAD));
- // 1998-07-23 Palette shift when player dies with quad/pentagram fix
- // by Maddes end
-
- // self.invisible_finished = 0; // don't die as eyes
- self.invincible_finished = 0;
- self.super_damage_finished = 0;
- self.radsuit_finished = 0;
-
- // 1998-07-23 Glowing corpse of players which had quad/pentagram
- // until respawn fix by Maddes
- self.effects = 0;
-
- // don't use eyes
- self.modelindex = modelindex_player;
-
- if (deathmatch || coop)
- item_backpack::drop_backpack (self.origin, self.weapon, self.ammo_shells, self.ammo_nails, self.ammo_rockets, self.ammo_cells);
-
- self.weaponmodel = "";
- self.view_ofs = '0 0 -8';
- self.deadflag = DEAD_DYING;
- self.solid = SOLID_NOT;
- self.flags = self.flags - (self.flags & FL_ONGROUND);
- self.movetype = MOVETYPE_TOSS;
-
- if (self.velocity_z < 10)
- self.velocity_z = self.velocity_z + random() * 300;
-
- if (self.health < -40)
- {
- GibPlayer ();
- return;
- }
-
- PlayerDeathSound ();
-
- self.angles_x = 0;
- self.angles_z = 0;
-
- if (self.weapon == IT_AXE)
- {
- player_die_ax1 ();
- return;
- }
-
- i = cvar ("temp1");
- if (!i)
- i = 1 + floor (random() * 6);
-
- if (i == 1)
- player_diea1 ();
- else if (i == 2)
- player_dieb1 ();
- else if (i == 3)
- player_diec1 ();
- else if (i == 4)
- player_died1 ();
- else
- player_diee1 ();
-};
-
-//----------------------------------------------------------------------
-void() set_suicide_frame =
-{
- // used by klill command and diconnect command
- if (self.model != "progs/player.mdl")
- // allready gibbed
- return;
- self.frame = $deatha11;
- self.solid = SOLID_NOT;
- self.movetype = MOVETYPE_TOSS;
- self.deadflag = DEAD_DEAD;
- self.nextthink = -1;
-};
-
-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 (); };
-
-//======================================================================
-// Scenic Dead Monster Patch stuff here from DeadStuff mod -- dumptruck_ds
-//======================================================================
-
-/*QUAKED player_dead_axe (0 0.5 0.8) (-16 -16 -24) (16 16 32) SOLID X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-{
- model ({"path":"progs/player.mdl","frame":49});
-}
-*/
-void() player_dead_axe =
-{
- // new spawnflags for all entities -- iw
- if (SUB_Inhibit())
- return;
-
- precache_model ("progs/player.mdl");
- setmodel (self, "progs/player.mdl");
- self.frame = $axdeth9;
-
- if (self.spawnflags & 1)
- {
- self.solid = SOLID_BBOX;
- setsize (self,'-38.72 -5.83 -50.45','28.73 33.85 30');
- }
- else
- {
- self.solid = SOLID_NOT;
- }
-};
-
-/*QUAKED player_dead_face_down (0 0.5 0.8) (-16 -16 -24) (16 16 32) SOLID X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-{
- model ({"path":"progs/player.mdl","frame":84});
-}
-*/
-void() player_dead_face_down =
-{
- // new spawnflags for all entities -- iw
- if (SUB_Inhibit())
- return;
-
- precache_model ("progs/player.mdl");
- setmodel (self, "progs/player.mdl");
- self.frame = $deathc14;
-
- if (self.spawnflags & 1)
- {
- self.solid = SOLID_BBOX;
- setsize (self,'-50.28 -23.55 -49.85','30.66 14.49 30');
- }
- else
- {
- self.solid = SOLID_NOT;
- }
-};
-
-/*QUAKED player_dead_on_side (0 0.5 0.8) (-16 -16 -24) (16 16 32) SOLID X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-{
- model ({"path":"progs/player.mdl","frame":102});
-}
-*/
-void() player_dead_on_side =
-{
- // new spawnflags for all entities -- iw
- if (SUB_Inhibit())
- return;
-
- precache_model ("progs/player.mdl");
- setmodel (self, "progs/player.mdl");
- self.frame = $deathe9;
-
- if (self.spawnflags & 1)
- {
- self.solid = SOLID_BBOX;
- setsize (self,'-38.72 -5.83 -50.45','28.73 33.85 30');
- }
- else
- {
- self.solid = SOLID_NOT;
- }
-};
-
-//======================================================================
-// END Scenic Dead Monster Patch stuff here from DeadStuff mod -- dumptruck_ds
-//======================================================================
-
-/*QUAKED info_player_deathmatch (1 0 1) (-16 -16 -24) (16 16 24) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-{
-model ("progs/player.mdl");
-}
-potential spawning position for deathmatch games
-*/
-void() info_player_deathmatch =
-{
- // new spawnflags for all entities -- iw
- if (SUB_Inhibit())
- return;
-
- self.alpha = 0.2;
- self.model = "progs/player.mdl";
- self.frame = $axstnd1;
- setmodel (self, self.model);
-};
Return to the top of this page or return to the overview of this repo.
Diff qc/player/playerthink.qc
diff --git a/qc/player/playerthink.qc b/qc/player/playerthink.qc
deleted file mode 100644
index 260b292..0000000
--- a/qc/player/playerthink.qc
+++ /dev/null
@@ -1,616 +0,0 @@
-//==============================================================================
-// player/playerthink.qc
-//==============================================================================
-
-// fields
-.float dmgtime;
-
-//----------------------------------------------------------------------
-void() PlayerDeathThink =
-{
- local float forward;
-
- if ((self.flags & FL_ONGROUND))
- {
- forward = vlen (self.velocity);
- forward = forward - 20;
- if (forward <= 0)
- self.velocity = '0 0 0';
- else
- self.velocity = forward * normalize (self.velocity);
- }
-
- // wait for all buttons released
- if (self.deadflag == DEAD_DEAD)
- {
- if (self.button2 || self.button1 || self.button0)
- return;
- self.deadflag = DEAD_RESPAWNABLE;
- return;
- }
-
- // wait for any button down
- if (!self.button2 && !self.button1 && !self.button0)
- return;
-
- self.button0 = 0;
- self.button1 = 0;
- self.button2 = 0;
- respawn ();
-};
-
-//----------------------------------------------------------------------
-// PlayerClimb -- johnfitz
-//----------------------------------------------------------------------
-void() PlayerClimb =
-{
- self.velocity = '0 0 160';
-}
-
-//----------------------------------------------------------------------
-// PlayerJump
-//----------------------------------------------------------------------
-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;
- }
-
- // refactoring from Copper -- dumptruck_ds
- if (self.movetype != MOVETYPE_NOCLIP)
- {
- if (!(self.flags & FL_ONGROUND))
- return;
- // don't pogo stick
- if ( !(self.flags & FL_JUMPRELEASED) )
- return;
- // player jumping sound (h00rt)
- sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
- }
-
- self.flags = self.flags - (self.flags & FL_JUMPRELEASED);
-
- // don't stairwalk
- self.flags = self.flags - FL_ONGROUND;
-
- self.button2 = 0;
- self.velocity_z = self.velocity_z + 270;
-};
-
-//----------------------------------------------------------------------
-// WaterMove
-//----------------------------------------------------------------------
-void() WaterMove =
-{
- if (self.movetype == MOVETYPE_NOCLIP)
- {
- self.air_finished = time + 120;
- return;
- }
-
- if (self.health < 0)
- return;
-
- 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;
- self.deathtype = "drowning";
- T_Damage (self, world, world, self.dmg);
- self.deathtype = "";
- 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;
-
- self.deathtype = "lava";
- T_Damage (self, world, world, 10 * self.waterlevel);
- self.deathtype = "";
- }
- }
- else if (self.watertype == CONTENT_SLIME)
- {
- // do damage
- if (self.dmgtime < time && self.radsuit_finished < time)
- {
- self.dmgtime = time + 1;
- self.deathtype = "slime";
- T_Damage (self, world, world, 4 * self.waterlevel);
- self.deathtype = "";
- }
- }
-
- 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;
- }
-};
-
-//----------------------------------------------------------------------
-// CheckWaterJump
-//----------------------------------------------------------------------
-void() CheckWaterJump =
-{
- // from Copper -- dumptruck_ds
- if (self.movetype == MOVETYPE_NOCLIP)
- return;
-
- 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 & FL_JUMPRELEASED;
- // safety net
- self.teleport_time = time + 2; // safety net
- return;
- }
- }
-};
-
-//----------------------------------------------------------------------
-// PlayerPreThink -- Called every frame before physics are run
-//----------------------------------------------------------------------
-void() PlayerPreThink =
-{
- local float do_ladder_physics = FALSE;
-
- if (intermission_running)
- {
- // otherwise a button could be missed between the think tics
- IntermissionThink ();
- return;
- }
-
- if (self.view_ofs == '0 0 0')
- {
- // Check for cutscene stuff.
- Cutscene_Think ();
- // intermission or finale
- return;
- }
-
- // note that this code block is here, before the tests which check
- // whether the player is dead, so that the player's gravity will be
- // correctly updated even if they e.g. fell off a ladder because
- // they died -- iw
- if (autocvar(pm_standardphysics, FALSE))
- {
- if (self.pmove_flags & PMF_ONLADDER)
- {
- do_ladder_physics = TRUE;
- // not zero, because zero means "default"
- self.gravity = 0.0000001;
- self.pmove_flags &= ~PMF_ONLADDER;
- }
- else
- {
- do_ladder_physics = FALSE;
- self.gravity = self.wantedgravity;
- }
- }
- else
- {
- self.gravity = self.wantedgravity;
- }
-
- // If just spawned in, try to recover previous fog values from
- // own client entity, if any
- if (cleanUpClientStuff)
- fog_setFromEnt(self, self);
-
- // is this still used?
- makevectors (self.v_angle);
-
- CheckRules ();
- WaterMove ();
-
- // Run legacy CheckWaterJump if we're doing standard physics -- CEV
- if (autocvar(pm_standardphysics, FALSE))
- if (self.waterlevel == 2)
- CheckWaterJump ();
-
- if (self.deadflag >= DEAD_DEAD)
- {
- PlayerDeathThink ();
- return;
- }
-
- if (self.deadflag == DEAD_DYING)
- // dying, so do nothing
- return;
-
- // johnfitz ladder conditions, added from Rubicon2 -- dumptruck_ds
- if (autocvar(pm_standardphysics, FALSE))
- {
- if (do_ladder_physics)
- {
- if (self.button2)
- {
- PlayerClimb ();
- /*
- // no ladder footsteps for now
- if (time > self.ladder_step_finished)
- {
- r = random();
- if (r > 0.66)
- sound (self, CHAN_BODY,
- "ladder/metal1.wav",
- 0.5, ATTN_NORM);
- else if (r > 0.33)
- sound (self, CHAN_BODY,
- "ladder/metal2.wav",
- 0.5, ATTN_NORM);
- else
- sound (self, CHAN_BODY,
- "ladder/metal3.wav",
- 0.5, ATTN_NORM);
- self.ladder_step_finished = time + 0.3;
- }
- */
- }
- else
- {
- self.flags = self.flags | FL_JUMPRELEASED;
- self.velocity = 0.9 * self.velocity;
- self.velocity_z = 0;
- }
- }
- else
- {
- 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';
-
- if (time > self.attack_finished && self.currentammo == 0
- && self.weapon != IT_AXE)
- {
- self.weapon = PlayerBestWeapon ();
- PlayerSetCurrentAmmo ();
- }
-
- // from copper -- dumptruck_ds
- if (autocvar(pm_standardphysics, FALSE))
- {
- if (self.movetype == MOVETYPE_NOCLIP)
- {
- self.flags = self.flags | FL_FLY;
- }
- }
-
- // TODO CEV
- if (self.groundboost_timer <= 0 && (self.teleport_time > time - 0.1))
- self.groundboost_timer = PM_GROUNDBOOST_WINDOW;
-};
-
-//----------------------------------------------------------------------
-// CheckPowerups -- Check for turning off powerups
-//----------------------------------------------------------------------
-void() CheckPowerups =
-{
- if (self.health <= 0) return;
-
- // 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
- {
- // don't use the eyes
- self.modelindex = modelindex_player;
- }
-
- // 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 & 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 & EF_DIMLIGHT;
- }
-
- // suit
- if (self.radsuit_finished)
- {
- // don't drown
- self.air_finished = time + 12;
-
- // 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 =
-{
- // TODO CEV
- self.SendFlags = 0xffffff;
-
- if (self.view_ofs == '0 0 0')
- // intermission or finale
- return;
- if (self.deadflag)
- return;
-
- // next block was in W_WeaponFrame -- CEV
- if (time >= self.attack_finished)
- {
- if (self.impulse)
- ImpulseCommands ();
- if (self.button0)
- {
- SuperDamageSound ();
- PlayerAttack ();
- }
- }
-
- // check to see if player landed and play landing sound
- 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)
- {
- self.deathtype = "falling";
- T_Damage (self, world, world, 5);
- self.deathtype = "";
- sound (self, CHAN_VOICE, "player/land2.wav",
- 1, ATTN_NORM);
- }
- 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;
-
- // dumptruck_ds -- this replaces item_megahealth_rot in items.qc
- if (self.health > self.max_health)
- {
- if (self.megahealth_rottime < time)
- {
- self.megahealth_rottime = time + 1;
- self.health = self.health - 1;
- }
- else if (self.health <= 100)
- {
- // thanks ydrol!!!
- self.items = self.items - (self.items & IT_SUPERHEALTH);
- }
- }
-
- CheckPowerups ();
-
- // from Copper -- dumptruck_ds
- if (autocvar(pm_standardphysics, FALSE))
- if (self.movetype != MOVETYPE_NOCLIP)
- // self.flags = not(self.flags, FL_FLY);
- self.flags &= ~FL_FLY;
-};
Return to the top of this page or return to the overview of this repo.
Diff qc/player/pmove.qc
diff --git a/qc/player/pmove.qc b/qc/player/pmove.qc
deleted file mode 100644
index ed699d7..0000000
--- a/qc/player/pmove.qc
+++ /dev/null
@@ -1,2179 +0,0 @@
-//==============================================================================
-// PMOVE
-//==============================================================================
-
-// TODO CEV: crouching
-// TODO CEV: crouch sliding (useful for sliding up stairs)
-// TODO CEV: crouch-wall-thing (wallrunning? wall sliding?)
-// TODO CEV: improved player unstick function
-// TODO CEV: more work on walking
-// TODO CEV: varied sounds (footsteps, different jump sounds)
-
-// globals managed by FTEQW, from fteextensions.qc -- CEV
-float input_buttons;
-// float input_impulse;
-float input_timelength;
-vector input_angles; // +x = DOWN
-vector input_movevalues;
-
-// fields
-// note: timers are expensive, require synch between server and client -- CEV
-// .entity groundentity;
-.vector groundnormal;
-.float pmove_flags; // custom movement flags -- CEV
-.float doublejump_timer; // time in which a player can doublejump
-.float groundboost_timer; // time to apply low friction -- CEV
-.void() customphysics;
-
-// pmove constants; it's definitely possible to rework these as cvars -- CEV
-// acceleration & friction
-const float PM_AIRACCEL = 7.5f; // 10 in Q1; now 7.5 or 8.0
-const float PM_AIRACCELQ3 = 0.75f; // 1.0 in Q3 ?; now 0.75 or 0.8
-const float PM_AIRACCELFWD = 0.75f; // 1 feels close to Q3 / CPM
-const float PM_AIRACCELBACK = 5.0f; // Air stop speed in Q3?
-const float PM_AIRACCELTURN = 100.0f; // affects +fwd style turning radius
-const float PM_BOOSTACCEL = 11.25f; // ground boost accel; 10; 10 + 1.25
-const float PM_BOOSTFRICTION = 4.0f; // ground boost friction; 4 is Q1
-const float PM_GROUNDACCEL = 13.75f; // 10 is Q1, 15 is CPM; 15 - 1.25
-const float PM_GROUNDFRICTION = 8.0f; // 4 for Q1, 6 for Q3, 8 for (old?) CPM
-const vector PM_GROUNDDIST_V = '0 0 1'; // distance for ground check
-const float PM_WATERACCEL = 10.0f; // water acceleration
-const float PM_WATERFRICTION = 4.0f; // friction in water
-
-// horizontal speeds (mostly)
-const float PM_CROUCHSPEED = 120.0f; // ???
-const float PM_MAXSPEED = 320.0f; // 320 always
-const float PM_MAXAIRSPEED = 30.0f; // 30 for Q1 air control
-const float PM_RUNSPEED = 400.0f; // run speed override
-const float PM_STOPSPEED = 100.0f;
-const float PM_TELEEXITSPEED = 400.0f; // exit teleporters at this speed
-const float PM_WALKSPEED = 200.0f; // walk speed override
-const float PM_WATERMAXSPEED = 224.0f; // 320 * 0.7
-const float PM_WATERSINKSPEED = 60.0f;
-
-// vertical speeds (mostly)
-const float PM_GRAVITY = 800.0f; // unless sv_gravity, scaled by .gravity
-const float PM_JUMPSPEED = 270.0f; // standard jump Z velocity; 90 * 3
-const float PM_DOUBLEJUMPSPEED = 270.0f;// 270 * 1.5 in CPM; 360 here
-const float PM_STAIRJUMPSPEED = 360.0f; // 360 = 90 * 4
-const float PM_TELEJUMPSPEED = 360.0f; // same as STAIRJUMPSPEED
-const float PM_WALLJUMPFORCE = 90.0f; // 90 * 2; push away from wall
-const float PM_WALLJUMPGROUND = 20.0f; // distance from ground to allow WJ (36)
-const float PM_WALLJUMPLIMIT = -225.f; // no walljump if Z vel below this
-const float PM_WALLJUMPSPEED = 270.0f; // 225 = 90 * 2.5; wall jump
-const float PM_WALLJUMPDOUBLE = 360.0f; // 315 = 90 * 3.5; wall doublejump
-
-// timing
-const float PM_DOUBLEJUMP_WINDOW = 0.4f;// 2 jumps in this time is a double
-const float PM_GROUNDBOOST_WINDOW = 0.4f;// groundboost duration
-const float PM_TELEJUMP_WINDOW = 0.4f; // duration to perform a telejump
-const float PM_WALLJUMP_WINDOW = 0.2f; // duration between walljumps
-const float PM_WALLCLIP_WINDOW = 0.25f; //
-
-// misc
-const float PM_OVERCLIP = 1.0f; // Quake3's OVERCLIP is 1.001f
-const float PM_ONESIDEDCLIP = -0.1; // -0.001;
-const float PM_STEPHEIGHT = 18.0f; // 18 for Q1, 22 for later games?
-const vector PM_TELEDROP = '0 0 -64'; // drop teleporter exit to floor if
- // floor is within this distance
-// water level
-const int WATERLEVEL_NONE = 0;
-const int WATERLEVEL_FEET = 1;
-const int WATERLEVEL_WAIST = 2;
-const int WATERLEVEL_EYES = 3;
-
-//
-const vector CROUCHED_MINS = '-16 -16 -18';// VEC_HULL_MIN is '-16 -16 -24'
-const vector CROUCHED_MAXS = '16 16 18';// VEC_HULL_MAX is '16 16 32'
-
-// pmove_flags
-enumflags
-{
- PMF_ONGROUND, // entity is on ground
- PMF_STARTGROUND, // entity started the move on ground
- PMF_ONLADDER, // entity is on a ladder
- PMF_INWATER, // entity is in water
- PMF_CROUCH_HELD, // player is holding the crouch key
- PMF_CROUCHED, // entity is crouching
- PMF_JUMP_HELD, // player is holding the jump key
- PMF_DOUBLEJUMPED, // entity has doublejumped
- PMF_WALLJUMPED, // entity has walljumped
- PMF_WATERJUMPED, // entity has waterjumped
- PMF_PRE_MOVE // hint that origin hasn't updated yet
-};
-
-// prototypes
-static void(entity ent) PM_DoTouch;
-float() PM_Nudge;
-void(float dogravity, float sticky, float dostep, float doskim) PM_DanceMove;
-void() PM_CategorizePosition;
-void(float friction, float move_time) PM_Friction;
-void(vector wishdir, float wishspeed, float accel, float move_time)
- PM_Accelerate;
-void(vector wishvel, float wishspeed, float accel, float move_time)
- PM_AirAccelerate;
-void(vector wishdir, float wishspeed, float move_time) PM_AirControl;
-void() PM_Jump;
-void() PM_WallJump;
-void(vector wishvel, float move_time) PM_WalkAccelerate;
-void(vector wishvel, float move_time) PM_SwimAccelerate;
-void(vector wishvel, float scale, float move_time) PM_NoClipAccelerate;
-void(float move_time) PM_ManageTimers;
-void(entity target) PM_Move;
-
-#ifdef SSQC
-//----------------------------------------------------------------------
-// SV_RunClientCommand -- server-side movement entrypoint -- CEV
-//----------------------------------------------------------------------
-void() SV_RunClientCommand =
-{
- // should match the one used by csqc.
- if (autocvar(pm_standardphysics, FALSE))
- // for testing -- CEV
- runstandardplayerphysics (self);
- else
- // for real
- PM_Move (self);
-};
-#endif
-
-//----------------------------------------------------------------------
-// PM_DoTouch
-//----------------------------------------------------------------------
-static void(entity ent) PM_DoTouch =
-{
-#ifdef SSQC
- if (ent && (ent.classgroup & CG_MAPENTITY))
- {
- other = self;
- ((base_mapentity)ent).touch ();
- return;
- }
-#endif
- if (ent && ent.touch != __NULL__)
- {
- local entity orig_self;
-
- orig_self = self;
- other = self;
- self = ent;
- self.touch ();
- self = orig_self;
- }
-};
-
-//----------------------------------------------------------------------
-// PM_Nudge
-// from the GPL2 CSQCTest code that comes with FTEQW; is called often
-// to nudge player origin due to float/network precision errors -- CEV
-//----------------------------------------------------------------------
-float() PM_Nudge =
-{
- vector test, org = self.origin;
-
- // check current position.
- tracebox (org, self.mins, self.maxs, org, FALSE, self);
- if (!trace_startsolid)
- return TRUE;
-
- // truncate to network accuracy
- org_x = floor (org_x * 8 + (1.0 / 16)) * 0.125;
- org_y = floor (org_y * 8 + (1.0 / 16)) * 0.125;
- org_z = floor (org_z * 8 + (1.0 / 16)) * 0.125;
-
- test = org;
-
- static float offsets[] = {0, -1./8, 1./8, -2./8, 2./8};
- for (float z = 0; z < offsets.length; z++)
- {
- test.z = org.z + offsets[z];
- for (float y = 0; y < offsets.length; y++)
- {
- test.y = org.y + offsets[y];
- for (float x = 0; x < offsets.length; x++)
- {
- test.x = org.x + offsets[x];
- tracebox (test, self.mins, self.maxs, test,
- FALSE, self);
- if (!trace_startsolid)
- {
- // okay, that'll do
- self.origin = test;
- return TRUE;
- }
- }
- }
- }
- self.origin = org;
- return FALSE;
-};
-
-//----------------------------------------------------------------------
-// PM_DanceMove
-//
-// Updates origin according to velocity, moves the player through the world.
-// Same as Q3 SlideMove and Q1 FlyMove. This version handles steps, applies
-// gravity, and restores velocity based on a timer check (those latter two
-// are features of Q3's SlideMove). I've inlined a number of functions
-// (ClipVelocity, DoTouch) to hopefully improve performance.
-//
-// Based on code from the Nuclide SDK (presumably by Eukara), specifically
-// the function PMoveCustom_Move found in the file pmove_custom.qc. This
-// in turn appears to be based on a similar function in the CSQCTest code
-// that comes with FTEQW. -- CEV
-//----------------------------------------------------------------------
-void(float dogravity, float sticky, float dostep, float doskim) PM_DanceMove =
-{
- vector end, prev_plane, prev_plane2, plane, start_v;
- float backoff, grav, stepsize, time_left;
- int i;
- entity touched_ent;
-
- // silence some FTEQCC warnings -- CEV
- end = prev_plane = prev_plane2 = plane = start_v = '0 0 0';
- backoff = grav = stepsize = time_left = 0;
-
- if (dogravity)
- {
- if (self.gravity)
- grav = self.gravity;
- else
- grav = 1.0;
- grav = grav * autocvar (sv_gravity, PM_GRAVITY) *
- input_timelength;
- // Half now, half later. Apparently affects framerate
- // dependence. -- CEV
- self.velocity_z -= grav * 0.5;
- }
-
- start_v = self.velocity;
-
- // Borrowing FTEQW's pm_airstep cvar here. If false, don't step up
- // while in the air (changes stairs) -- CEV
- if (!(autocvar(pm_airstep, TRUE)) && !(self.pmove_flags & PMF_ONGROUND))
- dostep = FALSE;
-
- // no stepping. useful for testing -- CEV
- if (autocvar(pm_nostep, FALSE))
- dostep = FALSE;
-
- // we need to bounce off surfaces (in order to slide along them),
- // so we need at 2 attempts -- comment from the Nuclide SDK
- // I've changed this to a larger number of attempts (from 3 to 5)
- // to accommodate more complex plane interactions -- CEV
- for (i = 5, time_left = input_timelength; time_left > 0 && i; i--)
- {
- // set our destination & test the move -- CEV
- end = self.origin + (self.velocity * time_left);
- tracebox (self.origin, self.mins, self.maxs, end, FALSE, self);
-
- if (trace_allsolid || trace_startsolid)
- {
- // entity is trapped in a solid; attempt to nudge out
- if (PM_Nudge())
- continue;
-
- // nah, we're stuck. don't build up falling damage
- // but allow sideways acceleration -- CEV
- /*
- #ifdef CSQC
- dprint ("PM_DanceMove: client ");
- #endif
- #ifdef SSQC
- dprint ("PM_DanceMove: server ");
- #endif
- #if defined(CSQC) || defined(SSQC)
- dprint ("entity trapped in a solid!\n");
- #endif
- */
- self.velocity_z = 0;
- break;
- }
-
- // accept the move -- CEV
- self.origin = trace_endpos;
-
- if (trace_fraction >= 1.0f)
- // no obstructions, made the whole move -- CEV
- break;
-
- // zero out stepsize, then store the plane normal and touched
- // ent for later, then reduce time_left -- CEV
- stepsize = 0;
- plane = trace_plane_normal;
- touched_ent = trace_ent;
- time_left -= time_left * trace_fraction;
-
- // integrated StepSlideMove from Nuclide / CSQCTest -- CEV
- // only attempt to step if there's time left, stepping was
- // requested, and we hit something like a vertical plane
- if (dostep && time_left && plane_z >= 0 && plane_z <= 0.7f)
- {
- // first: move up
- trace_endpos = self.origin;
- trace_endpos_z += PM_STEPHEIGHT;
- tracebox (self.origin, self.mins, self.maxs,
- trace_endpos, FALSE, self);
-
- // don't like having to store another float & vector
- // but this solves more interactions (ztndm3) -- CEV
- local float roof_fraction = trace_fraction;
- local vector roof_plane = trace_plane_normal;
-
- // second: move forward
- stepsize = trace_endpos_z - self.origin_z;
- end = trace_endpos + (self.velocity * time_left);
- end_z = trace_endpos_z;
- tracebox (trace_endpos, self.mins, self.maxs, end,
- FALSE, self);
-
- // save trace_ent if it has a touch function
- if (trace_ent && trace_ent.touch != __NULL__)
- touched_ent = trace_ent;
-
- if (trace_allsolid || trace_startsolid)
- {
- // reject the move immediately -- CEV
- #ifdef SSQC
- dprint ("PM_DanceMove: fwd move solid\n");
- #endif
- stepsize = 0;
- self.velocity = '0 0 0';
- break;
- }
- else if (trace_fraction >= 1.0f)
- {
- // storing another vector, disappointed in
- // myself -- CEV
- local vector fwd_plane = trace_plane_normal;
-
- // forward move didn't hit anything
- // third: move down
- end = trace_endpos;
- end_z -= stepsize + 1;
- tracebox (trace_endpos, self.mins, self.maxs,
- end, FALSE, self);
-
- if (trace_allsolid || trace_startsolid)
- {
- // again reject the move -- CEV
- #ifdef SSQC
- dprint ("PM_DanceMove: down move "
- "solid\n");
- #endif
- stepsize = 0;
- self.velocity = '0 0 0';
- break;
- }
- else if (trace_fraction < 1.0f &&
- trace_plane_normal_z > 0.7f)
- {
- // good ground, accept the move
- if (roof_fraction < 1.0f &&
- roof_plane != fwd_plane &&
- roof_plane != plane)
- {
- // do a simple clipvel to the
- // roof plane right now -- CEV
- self.velocity -= roof_plane *
- (self.velocity *
- roof_plane);
- }
-
- stepsize = trace_endpos_z -
- self.origin_z;
- self.origin = trace_endpos;
- time_left -= time_left * trace_fraction;
-
- prev_plane2 = __NULL__;
- prev_plane = fwd_plane;
- plane = trace_plane_normal;
-
- if (trace_ent &&
- trace_ent.touch != __NULL__)
- touched_ent = trace_ent;
-
- // don't attempt to step again
- dostep = FALSE;
- }
- else
- {
- // down move didn't hit and/or
- // it hit a plane too steep to
- // be ground -- CEV
- stepsize = 0;
- }
- }
- else if (trace_plane_normal != plane)
- {
- // raised forward move hit something different
- // than the initial move so clip velocity to
- // it. solves issues with weird ceilings and
- // complex movement on stairs. note that we're
- // not updating origin. -- CEV
- prev_plane2 = __NULL__;
- prev_plane = __NULL__;
- time_left -= time_left * trace_fraction;
- stepsize = 0;
-
- if (roof_fraction < 1.0f &&
- roof_plane != trace_plane_normal)
- {
- // save the roof plane & fwd plane
- prev_plane = roof_plane;
- plane = trace_plane_normal;
- }
- else if (roof_plane == trace_plane_normal)
- {
- // roof plane is fwd plane, so save
- // first and fwd plane
- prev_plane = plane;
- plane = trace_plane_normal;
- }
- else
- {
- // only save fwd plane
- plane = trace_plane_normal;
- }
- }
- }
-
- // need to do the ground check & touch the saved ent before
- // we might stop the loop early -- CEV
- if (plane_z > 0.7)
- {
- if (touched_ent.solid == SOLID_BSP)
- {
- self.groundentity = touched_ent;
- self.groundnormal = plane;
- self.flags |= FL_ONGROUND;
- self.pmove_flags |= PMF_ONGROUND;
- }
- }
- else
- {
- self.groundentity = __NULL__;
- self.groundnormal = __NULL__;
- self.flags &= ~FL_ONGROUND;
- self.pmove_flags &= ~PMF_ONGROUND;
- }
-
- // touch the saved entity; inline PM_DoTouch -- CEV
- if (touched_ent && touched_ent.touch != __NULL__)
- {
- PM_DoTouch (touched_ent);
- /*
- local entity orig_self;
-
- orig_self = self;
- other = self;
- self = touched_ent;
- self.touch ();
- self = orig_self;
- */
- }
-
- // clip velocity to the saved plane
- // inline PM_Rebound aka PM_ClipVelocity -- CEV
- backoff = self.velocity * plane;
-
- if (backoff < 0)
- backoff *= PM_OVERCLIP;
- else
- if (sticky)
- backoff /= PM_OVERCLIP;
- else
- backoff *= PM_ONESIDEDCLIP;
-
- self.velocity -= plane * backoff;
-
- // if velocity interacts with prev_plane then clip to it.
- // I'm duplicating a little code here (ClipVelocity),
- // hopefully the audience will forgive me. -- CEV
- if (prev_plane && prev_plane != plane &&
- self.velocity * prev_plane < 0)
- {
- backoff = self.velocity * prev_plane;
-
- if (backoff < 0)
- backoff *= PM_OVERCLIP;
- else
- if (sticky)
- backoff /= PM_OVERCLIP;
- else
- backoff *= PM_ONESIDEDCLIP;
-
- self.velocity -= prev_plane * backoff;
-
- // Slide along the crease of previous plane and
- // current plane if the two still interact -- CEV
- if (self.velocity * plane < 0)
- {
- end = crossproduct (prev_plane, plane);
- end = normalize (end);
- self.velocity = end * (end * self.velocity);
- }
-
- // An optimization from Quake 3 -- CEV
- if (prev_plane2 && prev_plane2 != plane &&
- prev_plane2 != prev_plane &&
- self.velocity * prev_plane2 < 0)
- {
- // Stop if we interact with three planes -- CEV
- #ifdef SSQC
- dprint ("PM_DanceMove: triple plane stop\n");
- #endif
- self.velocity = '0 0 0';
- break;
- }
- }
-
- // an optimization from Quake 1; is this necessary? -- CEV
- if ((self.velocity * start_v) <= 0)
- {
- // we've turned against original velocity so
- // clear vel and stop the loop
- self.velocity = '0 0 0';
- break;
- }
-
- // store current plane and prev_plane for later -- CEV
- if (prev_plane)
- prev_plane2 = prev_plane;
- prev_plane = plane;
- }
-
- // wallclip / wall skim timer check
- // if doskim is true and velocity is non-zero and we lost speed
- // during the move then restore velocity -- CEV
- if (doskim && self.velocity && (vlen(start_v) > vlen(self.velocity)))
- {
- /*
- #ifdef SSQC
- dprint ("PM_DanceMove: wall skim, restoring velocity...\n");
- #endif
- */
- // take the start Z or clipped Z, whichever is lower -- CEV
- if (start_v_z > self.velocity_z)
- self.velocity = [start_v_x, start_v_y, self.velocity_z];
- else
- self.velocity = start_v;
- }
-
- // final gravity check here -- CEV
- if (dogravity)
- self.velocity_z -= grav * 0.5;
-
- // if stepsize is nonzero and we changed from inair to onground then
- // we've airstepped. this check is here as a placeholder for possible
- // functionality later -- CEV
- #ifdef SSQC
- if (stepsize > 0 && !(self.pmove_flags & PMF_STARTGROUND) &&
- self.pmove_flags & PMF_ONGROUND)
- {
- // more debugging -- CEV
- dprint (sprintf("PM_DanceMove: airstep: %g\n", stepsize));
- }
- #endif
-
- // a final call to setorigin to update links -- CEV
- setorigin (self, self.origin);
-
- /*
- #ifdef SSQC
- if (cvar("developer"))
- // for debugging purposes -- CEV
- dprint (sprintf("PM_DanceMove: %g bumps\n", 5 - i));
- #endif
- */
-};
-
-//----------------------------------------------------------------------
-// PM_CategorizePosition
-// Based on similarly-named function in the GPL2 purecsqc pmove.qc
-//----------------------------------------------------------------------
-void() PM_CategorizePosition =
-{
- vector point;
- float contents;
-
- if (self.movetype == MOVETYPE_NOCLIP || self.movetype == MOVETYPE_FLY)
- {
- // noclip is never on ground
- self.groundentity = __NULL__;
- self.groundnormal = __NULL__;
- self.pmove_flags &= ~PMF_DOUBLEJUMPED;
- self.pmove_flags &= ~PMF_WALLJUMPED;
- self.pmove_flags &= ~PMF_ONGROUND;
- self.flags &= ~FL_ONGROUND;
- }
- else
- {
- // TODO CEV there must be a way to optimize out this
- // tracebox ground check some of the time
-
- // do a trace to check for ground
- tracebox (self.origin, self.mins, self.maxs,
- self.origin - PM_GROUNDDIST_V, FALSE, self);
- // only onground if we hit it & it faces upwards
- if (trace_fraction < 1.0f && trace_plane_normal_z > 0.7f)
- {
- // on ground
- self.groundentity = trace_ent;
- self.groundnormal = trace_plane_normal;
- self.flags |= FL_ONGROUND;
- self.pmove_flags |= PMF_ONGROUND;
- self.pmove_flags &= ~PMF_WALLJUMPED;
- }
- else
- {
- // not on ground
- self.groundentity = __NULL__;
- self.groundnormal = __NULL__;
- self.flags &= ~FL_ONGROUND;
- self.pmove_flags &= ~PMF_ONGROUND;
- }
- }
-
- // check water levels
- point = self.origin;
- point_z = self.origin_z + self.mins_z + 1;
- contents = pointcontents (point);
- if (contents < CONTENT_SOLID)
- {
- self.watertype = contents;
- point_z = self.origin_z + (self.mins_z + self.maxs_z) * 0.5;
- if (pointcontents(point) < CONTENT_SOLID)
- {
- point_z = self.origin_z + self.maxs_z;
- if (pointcontents(point) < CONTENT_SOLID)
- self.waterlevel = WATERLEVEL_EYES;
- else
- self.waterlevel = WATERLEVEL_WAIST;
- }
- else
- {
- self.waterlevel = WATERLEVEL_FEET;
- }
- }
- else
- {
- self.watertype = CONTENT_EMPTY;
- self.waterlevel = WATERLEVEL_NONE;
- }
-
- // can't be waterjumping if we're on ground
- if (self.pmove_flags & PMF_WATERJUMPED &&
- (self.waterlevel == WATERLEVEL_NONE ||
- self.pmove_flags & PMF_ONGROUND))
- {
- #ifdef SSQC
- dprint ("PM_CategorizePosition: clearing FL_WATERJUMP\n");
- #endif
- self.pmove_flags &= ~PMF_WATERJUMPED;
- self.flags &= ~FL_WATERJUMP;
- }
-};
-
-//----------------------------------------------------------------------
-// PM_Friction
-// Ground friction
-//----------------------------------------------------------------------
-void(float friction, float move_time) PM_Friction =
-{
- float control, newspeed, speed;
-
- speed = vlen (self.velocity);
-
- if (speed < 1)
- {
- self.velocity = '0 0 0';
- return;
- }
-
- // calculate what their new speed should be
- control = speed < PM_STOPSPEED ? PM_STOPSPEED : speed;
- newspeed = speed - control * friction * move_time;
-
- // and slow them
- if (newspeed < 0)
- newspeed = 0;
-
- self.velocity = self.velocity * (newspeed / speed);
-};
-
-//----------------------------------------------------------------------
-// PM_Accelerate
-// Ground acceleration & Quake 3 style air acceleration -- CEV
-//----------------------------------------------------------------------
-void(vector wishdir, float wishspeed, float accel, float move_time)
- PM_Accelerate =
-{
- float newspeed, speed;
-
- speed = wishspeed - (self.velocity * wishdir);
-
- if (speed <= 0)
- return;
-
- newspeed = accel * move_time * wishspeed;
- if (newspeed > speed)
- newspeed = speed;
-
- self.velocity += newspeed * wishdir;
-};
-
-//----------------------------------------------------------------------
-// PM_AirAccelerate
-// Quake 1 style air acceleration -- CEV
-//----------------------------------------------------------------------
-void(vector wishvel, float wishspeed, float accel, float move_time)
- PM_AirAccelerate =
-{
- float newspeed, speed, wishspd;
-
- // need to ignore Z velocity -- CEV
- wishvel = [wishvel_x, wishvel_y, 0];
- wishspd = vlen (wishvel);
- wishvel = normalize (wishvel);
- if (wishspd > PM_MAXAIRSPEED)
- wishspd = PM_MAXAIRSPEED;
- speed = self.velocity * wishvel;
- speed = wishspd - speed;
-
- if (speed <= 0)
- return;
-
- newspeed = accel * move_time * wishspeed;
- if (newspeed > speed)
- newspeed = speed;
- self.velocity += newspeed * wishvel;
-};
-
-//----------------------------------------------------------------------
-// PM_AirControl
-// CPM / Painkiller-like Air Control. Based on Xonotic sources. -- CEV
-//----------------------------------------------------------------------
-void(vector wishdir, float wishspeed, float move_time) PM_AirControl =
-{
- local float speed, zspeed;
-
- zspeed = self.velocity_z;
- self.velocity_z = 0;
-
- speed = vlen (self.velocity);
- self.velocity = normalize (self.velocity);
-
- if ((self.velocity * wishdir) > 0)
- {
- self.velocity = normalize (self.velocity * speed +
- wishdir * PM_AIRACCELTURN);
- }
-
- self.velocity *= speed;
- self.velocity_z = zspeed;
-};
-
-//----------------------------------------------------------------------
-// PM_Jump
-//----------------------------------------------------------------------
-void() PM_Jump =
-{
- // are we already waterjumping, or is jump being held?
- if (self.pmove_flags & PMF_WATERJUMPED ||
- self.pmove_flags & PMF_JUMP_HELD)
- return;
-
- #ifdef SSQC
- local string msg = "";
- #endif
-
- // make sure we get at least jumpspeed upwards from
- // the ground plane by clamping it first.
- if (self.groundnormal && (self.velocity * self.groundnormal < 0))
- {
- // #ifdef SSQC
- // dprint("PM_Jump: clamping to ground\n");
- // #endif
- self.velocity -= self.groundnormal *
- (self.velocity * self.groundnormal);
- }
-
- // make sure we get at least the indicated jump speed
- // this changes the behavior of downward ramps -- CEV
- if (self.velocity_z < 0)
- self.velocity_z = 0;
-
- if (self.doublejump_timer > 0)
- {
- // it may be useful in the future (for a tricks mode, etc)
- // to distinguish between different jump types -- CEV
- if (self.teleport_time > time - (PM_TELEJUMP_WINDOW + 0.2))
- {
- // a teleport jump: allow a larger (+0.2) window to
- // account for time to travel thru teleporter -- CEV
- #ifdef SSQC
- msg = sprintf ("PM_Jump: telejump %g, ",
- self.velocity_z);
- #endif
- // non-additive jump, though it shouldn't matter -- CEV
- self.velocity_z = PM_TELEJUMPSPEED;
- }
- else if (self.groundnormal && self.groundnormal_z == 1 &&
- self.groundboost_timer > 0)
- {
- #ifdef SSQC
- msg = sprintf ("PM_Jump: stairjump %g, ",
- self.velocity_z);
- #endif
- // don't do additive stairjumps on flat ground -- CEV
- self.velocity_z = PM_STAIRJUMPSPEED;
- }
- else
- {
- #ifdef SSQC
- msg = sprintf ("PM_Jump: doublejump %g, ",
- self.velocity_z);
- #endif
- // the groundnormal might be weird - some kind of
- // ramp - so we want an additive doublejump here -- CEV
- self.velocity_z += PM_DOUBLEJUMPSPEED;
- }
-
- // set the doublejump flag -- CEV
- self.pmove_flags |= PMF_DOUBLEJUMPED;
- }
- else
- {
- // normal jump
- #ifdef SSQC
- if (self.velocity_z > 0)
- msg = sprintf ("PM_Jump: jump %g, ", self.velocity_z);
- #endif
-
- // do an additive jump on non-flat ground -- CEV
- if (self.groundnormal_z == 1)
- self.velocity_z = PM_JUMPSPEED;
- else
- self.velocity_z += PM_JUMPSPEED;
- }
-
- // report new Z velocity
- #ifdef SSQC
- if (msg != "")
- dprint (sprintf("%s %g\n", msg, self.velocity_z));
- #endif
-
- // manage flags -- CEV
- self.groundentity = __NULL__;
- self.groundnormal = __NULL__;
- self.pmove_flags &= ~PMF_ONGROUND;
- self.flags &= ~FL_ONGROUND;
- self.pmove_flags |= PMF_JUMP_HELD;
- self.button2 = 0;
- #ifdef SSQC
- // player jumping sound; copied into pmove from client.qc -- CEV
- sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
- #endif
-
- // timers for all jumps -- CEV
- self.doublejump_timer = PM_DOUBLEJUMP_WINDOW;
- self.groundboost_timer = PM_GROUNDBOOST_WINDOW;
-};
-
-//----------------------------------------------------------------------
-// PM_WallJump
-//----------------------------------------------------------------------
-void() PM_WallJump =
-{
- // are we in water, already waterjumping, already walljumping,
- // or is jump being held?
- if (self.waterlevel > WATERLEVEL_NONE ||
- self.pmove_flags & PMF_WATERJUMPED ||
- self.pmove_flags & PMF_JUMP_HELD ||
- self.pmove_flags & PMF_WALLJUMPED)
- {
- /*
- #ifdef SSQC
- dprint ("PM_WallJump: returning in first block\n");
- #endif
- */
- return;
- }
-
- // mandatory interval between jump and walljump
- if (self.doublejump_timer > (PM_DOUBLEJUMP_WINDOW - PM_WALLJUMP_WINDOW))
- {
- /*
- #ifdef SSQC
- dprint ("PM_WallJump: returning, interval\n");
- #endif
- */
- return;
- }
-
- if (self.velocity_z < PM_WALLJUMPLIMIT)
- {
- // falling too fast to walljump
- // TODO CEV it would be a good idea to include a sound here.
- /*
- #ifdef SSQC
- dprint ("PM_WallJump: falling too fast, returning\n");
- #endif
- */
- return;
- }
-
- // minimum distance from ground to walljump
- local vector end = self.origin;
- end_z -= PM_WALLJUMPGROUND;
- tracebox (self.origin, self.mins, self.maxs, end, TRUE, self);
-
- if (trace_fraction < 1.0f)
- {
- /*
- #ifdef SSQC
- dprint ("PM_WallJump: too close to ground to walljump\n");
- #endif
- */
- return;
- }
-
- // start at STEPHEIGHT + 1 to try and clear any steps -- CEV
- local vector start;
- start = self.origin;
- start_z += PM_STEPHEIGHT + 1;
- end = start;
-
- for (int i = 0; i < 4; i++)
- {
- // I've borrowed a little logic from Quake Champions Classic
- // here, shoutout to RhapsodyInGeek, check out their good work
- // https://github.com/RhapsodyInGeek/Quake-Champions-Classic
- // v_forward and v_right should still correspond to the
- // makevectors call from PM_Move -- CEV
- if (i < 2)
- if (input_movevalues_x == 0)
- continue;
- else
- end = v_forward * 10;
- if (i > 1)
- if (input_movevalues_y == 0)
- continue;
- else
- end = v_right * 10;
- if (i == 1 || i == 3)
- end = end - end * 2;
-
- end = start + end;
-
- // this ends up firing *a lot* when hopping through a map
- // normally, unfortunately. traceline may be better here -- CEV
- tracebox (start, self.mins, self.maxs, end, TRUE, self);
-
- // in order: we hit something, that something is vaguely
- // vertical, we hit it at a speed greater than -90, and
- // that something is within 20 (units?) -- CEV
- if (trace_fraction < 1.0f &&
- trace_plane_normal_z <= 0.7f &&
- trace_plane_normal_z >= 0 &&
- self.velocity * trace_plane_normal >= -90 &&
- vlen(self.origin - trace_endpos) <= 20)
- {
- self.pmove_flags |= PMF_WALLJUMPED;
- break;
- }
- }
-
- if (self.pmove_flags & PMF_WALLJUMPED)
- {
- // bounce off the wall plane -- CEV
- self.velocity_x += trace_plane_normal_x * PM_WALLJUMPFORCE;
- self.velocity_y += trace_plane_normal_y * PM_WALLJUMPFORCE;
-
- // zero out negative Z, quarter positive Z -- CEV
- if (self.velocity_z < 0)
- self.velocity_z = 0;
- else if (self.velocity_z > 0)
- self.velocity_z *= 0.25;
-
- if (self.doublejump_timer > 0)
- {
- #ifdef SSQC
- dprint ("PM_WallJump: wall double ");
- #endif
- self.velocity_z += PM_WALLJUMPDOUBLE;
- }
- else
- {
- #ifdef SSQC
- dprint ("PM_WallJump: walljump ");
- #endif
- self.velocity_z += PM_WALLJUMPSPEED;
- }
-
- // manage flags & fields; PMF_WALLJUMPED is already set -- CEV
- self.pmove_flags |= PMF_JUMP_HELD;
- self.doublejump_timer = PM_DOUBLEJUMP_WINDOW;
-
- // server-side stuff
- #ifdef SSQC
- dprint (sprintf("dist %g, normalspeed %g\n",
- vlen(self.origin - trace_endpos),
- self.velocity * trace_plane_normal));
- self.button2 = 0;
- sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
- #endif
- }
-};
-
-//----------------------------------------------------------------------
-// PM_WalkAccelerate
-// Handle accel & friction for MOVETYPE_WALK entities (players). -- CEV
-//----------------------------------------------------------------------
-void(vector wishvel, float move_time) PM_WalkAccelerate =
-{
- vector wishdir;
- float accel, friction, newspeed, speed, temp, wishspeed;
-
- accel = friction = 0;
-
- wishspeed = vlen (wishvel);
- wishdir = normalize (wishvel);
-
- if (wishspeed > PM_MAXSPEED)
- wishspeed = PM_MAXSPEED;
-
- if (self.pmove_flags & PMF_PRE_MOVE)
- {
- if (self.pmove_flags & PMF_ONLADDER)
- {
- // ladder physics
- // these currently stutter in high ping (or low netfps)
- // situations because we rely on touch()ing the ladder
- // trigger to set PMF_ONLADDER and the client doesn't
- // know about the trigger brush yet -- TODO CEV
- self.velocity = 0.75 * self.velocity;
-
- if (input_buttons & 2 || self.button2 > 0 ||
- input_movevalues_z > 0)
- {
- // PlayerClimb -- johnfitz
- self.velocity_z = 160;
- }
- else if (input_movevalues_z < 0)
- {
- // PlayerClimbDown -- CEV
- self.velocity_z = -160;
- }
- else
- {
- self.flags |= FL_JUMPRELEASED;
- self.pmove_flags &= ~PMF_JUMP_HELD;
- self.velocity_z = 0;
- }
-
- self.pmove_flags &= ~PMF_ONGROUND;
- }
- else
- {
- if (input_buttons & 2 || self.button2 > 0 ||
- input_movevalues_z > 0)
- {
- // +jump was pressed
- if (self.pmove_flags & PMF_ONGROUND)
- {
- // normal jump
- PM_Jump ();
- }
- // TODO CEV
- /*
- else if (autocvar(pm_walljump, FALSE))
- */
- else
- {
- // borrow FTE's pm_walljump cvar -- CEV
- PM_WallJump ();
- }
- }
- else
- {
- self.flags |= FL_JUMPRELEASED;
- }
- }
-
- if (self.pmove_flags & PMF_ONGROUND)
- self.pmove_flags |= PMF_STARTGROUND;
- else
- self.pmove_flags &= ~PMF_STARTGROUND;
- }
-
- // Test STARTGROUND (the ONGROUND status post jump) to avoid
- // a ground friction frame when chaining jumps together.
- // Probably has unintended consequences. -- CEV
- if (self.pmove_flags & PMF_STARTGROUND)
- {
- // we're on ground so pick accel and friction values -- CEV
- if (self.groundboost_timer > 0)
- {
- accel = PM_BOOSTACCEL;
- friction = PM_BOOSTFRICTION;
- }
- else
- {
- accel = PM_GROUNDACCEL;
- friction = PM_GROUNDFRICTION;
- }
- }
- else if (input_movevalues_x == 0)
- {
- // Q1 air accel when requesting sideways movement in the air
- // flag a check below with this -1 -- CEV
- accel = -1;
- }
- else
- {
- if (input_movevalues_y == 0)
- {
- // Painkiller style air control
- if (wishvel * self.velocity < 0)
- // against original velocity; we're slowing down
- accel = PM_AIRACCELBACK;
- else
- // we're with original velocity - gaining speed
- accel = PM_AIRACCELFWD;
-
- // borrow the friction var to flag a conditional below
- friction = -1;
- }
- else
- {
- // we're in the air and the player is requesting both
- // forward/back and sideways movement, so pick the Q3
- // air accel value -- CEV
- accel = PM_AIRACCELQ3;
- }
- }
-
- // I've duplicated a fair amount of code below, inlining the various
- // acceleration functions to hopefully improve performance -- CEV
-
- // apply friction (ground or otherwise)
- if (friction > 0)
- {
- // inline PM_Friction
- speed = vlen (self.velocity);
-
- if (speed < 1)
- {
- self.velocity = '0 0 0';
- }
- else
- {
- // calculate what their new speed should be
- temp = speed < PM_STOPSPEED ? PM_STOPSPEED : speed;
- newspeed = speed - temp * friction * move_time;
-
- // and slow them
- if (newspeed < 0)
- newspeed = 0;
-
- self.velocity = self.velocity * (newspeed / speed);
- }
- }
-
- if (accel == -1)
- {
- // Quake 1 sideways air acceleration; inline PM_AirAccelerate
- wishvel_z = 0;
- temp = vlen (wishvel);
- wishvel = normalize (wishvel);
- if (temp > PM_MAXAIRSPEED)
- temp = PM_MAXAIRSPEED;
- speed = self.velocity * wishvel;
- speed = temp - speed;
-
- if (speed > 0)
- {
- newspeed = PM_AIRACCEL * move_time * wishspeed;
- if (newspeed > speed)
- newspeed = speed;
- self.velocity += newspeed * wishvel;
- }
- }
- else if (accel > 0)
- {
- // ground & Quake 3 style acceleration; inline PM_Accelerate
- speed = wishspeed - (self.velocity * wishdir);
-
- if (speed > 0)
- {
- newspeed = accel * move_time * wishspeed;
- if (newspeed > speed)
- newspeed = speed;
-
- self.velocity += newspeed * wishdir;
- }
- }
-
- // CPM & PK-style air control, needs to happen after PM_Accelerate
- if (friction == -1)
- {
- // inline PM_AirControl
- temp = self.velocity_z;
- self.velocity_z = 0;
-
- speed = vlen (self.velocity);
- self.velocity = normalize (self.velocity);
-
- if ((self.velocity * wishdir) > 0)
- {
- self.velocity = normalize (self.velocity * speed +
- wishdir * PM_AIRACCELTURN);
- }
-
- self.velocity *= speed;
- self.velocity_z = temp;
- }
-
- if (!(self.pmove_flags & PMF_PRE_MOVE))
- self.pmove_flags &= ~PMF_STARTGROUND;
-};
-
-//----------------------------------------------------------------------
-// PM_SwimAccelerate
-// Largely copied from id Software's WaterMove. Works like NoClipAccelerate.
-//----------------------------------------------------------------------
-void(vector wishvel, float move_time) PM_SwimAccelerate =
-{
- float wishspeed;
-
- if (self.pmove_flags & PMF_PRE_MOVE)
- {
- // CheckWaterJump
- if (self.waterlevel == WATERLEVEL_WAIST)
- {
- local vector start, end;
-
- start = self.origin;
- start_z = start_z + 8;
- // use wishvel instead of v_forward -- CEV
- end = [wishvel_x, wishvel_y, 0];
- end = normalize (end);
- traceline (start, (start + end * 24), TRUE, self);
-
- if (trace_fraction < 1)
- {
- // solid at the waist
- start_z = start_z + self.maxs_z - 8;
- self.movedir = trace_plane_normal * -50;
- traceline (start, (start + end * 24),
- TRUE, self);
-
- if (trace_fraction == 1)
- {
- // open at eye level
- self.flags |= FL_WATERJUMP;
- self.pmove_flags |= PMF_WATERJUMPED;
- self.flags &= ~FL_JUMPRELEASED;
- self.pmove_flags &= ~PMF_JUMP_HELD;
- // Z velocity was 225
- self.velocity_z = PM_JUMPSPEED;
- // we don't care about the 'safety net'
- // in this movement set (unlike vanilla)
- // so don't set teleport_time -- CEV
- // self.teleport_time = time + 2;
- }
- }
- }
-
- #ifdef SSQC
- // functionality copied into pmove from client.qc -- CEV
- if (self.waterlevel >= WATERLEVEL_WAIST)
- {
- if (self.swim_flag < time)
- {
- // play swimming sound
- 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);
- }
- }
- #endif
- }
-
- if (input_buttons & 2 && !(self.pmove_flags & PMF_WATERJUMPED))
- // smartjump
- wishvel_z = max (PM_MAXSPEED, wishvel_z);
- else if (input_movevalues == '0 0 0')
- // drift towards bottom -- CEV
- wishvel_z -= PM_WATERSINKSPEED;
-
- wishspeed = vlen (wishvel);
- if (wishspeed > PM_WATERMAXSPEED)
- wishspeed = PM_WATERMAXSPEED;
- wishvel = normalize (wishvel);
-
- // water friction; reuse PM_Friction with a special constant -- CEV
- if (!(self.pmove_flags & PMF_WATERJUMPED))
- PM_Friction (PM_WATERFRICTION, move_time);
-
- // accelerate; reuse PM_Accelerate with a special constant -- CEV
- PM_Accelerate (wishvel, wishspeed, PM_WATERACCEL, move_time);
-};
-
-//----------------------------------------------------------------------
-// PM_NoClipAccelerate
-//
-// Basic acceleration for flying / noclipping players. Not suitable for
-// swimming. -- CEV
-//----------------------------------------------------------------------
-void(vector wishvel, float scale, float move_time) PM_NoClipAccelerate =
-{
- float wishspeed;
-
- // smartjump
- if (input_buttons & 2)
- wishvel_z = max (PM_MAXSPEED, wishvel_z);
-
- wishspeed = vlen (wishvel) * scale;
- wishvel = normalize (wishvel);
-
- PM_Friction (PM_GROUNDFRICTION, move_time);
- PM_Accelerate (wishvel, wishspeed, PM_GROUNDACCEL, move_time);
-};
-
-//----------------------------------------------------------------------
-void(float move_time) PM_ManageTimers =
-{
- if (self.doublejump_timer > 0 && move_time > 0)
- self.doublejump_timer -= move_time;
- else if (self.doublejump_timer < 0)
- self.doublejump_timer = 0;
-
- if (self.doublejump_timer == 0)
- {
- self.pmove_flags &= ~PMF_DOUBLEJUMPED;
- }
-
- if (self.groundboost_timer > 0 && move_time > 0)
- self.groundboost_timer -= move_time;
- else if (self.groundboost_timer < 0)
- self.groundboost_timer = 0;
-};
-
-//----------------------------------------------------------------------
-// PM_Move -- PMOVE entrypoint -- CEV
-//----------------------------------------------------------------------
-void(entity target) PM_Move =
-{
- if (input_timelength <= 0)
- // don't process partial frames -- CEV
- return;
-
- vector wishvel;
- entity oldself;
-
- oldself = self;
- self = target;
-
- // Nudge player's origin if the server is sending low-precision
- // (16 bit?) player coordinates. This can be fixed by setting
- // sv_bigcoords to 1 (so the server sends float coords). -- CEV
- if (!autocvar(sv_bigcoords, FALSE))
- PM_Nudge ();
-
- // rework user input, copying something like QuakeSpasm's always run
- // feature here. This turns the +speed button into a hold-to-walk
- // button when cl_run is 0 (when FTE's always run setting is on).
- // -- CEV
- if (autocvar(cl_run, FALSE) == FALSE)
- {
- // local float s = 0;
- for (int i = 0; i < 3; i++)
- {
- // this works, it's just commented out to stop calling
- // autocvar quite so many times. to re-enable change
- // the check against "PM_RUNSPEED" below to "s" -- CEV
- /*
- if (i == 0)
- s = autocvar (cl_forwardspeed, PM_RUNSPEED);
- else if (i == 1)
- s = autocvar (cl_sidespeed, PM_RUNSPEED);
- else if (i == 2)
- s = autocvar (cl_upspeed, PM_RUNSPEED);
- */
-
- if (fabs(input_movevalues[i]) > PM_RUNSPEED)
- input_movevalues[i] = PM_WALKSPEED *
- (input_movevalues[i] /
- fabs(input_movevalues[i]));
- // Don't need this, it's already PM_RUNSPEED -- CEV
- /*
- else if (input_movevalues[i] != 0)
- input_movevalues[i] = PM_RUNSPEED *
- (input_movevalues[i] /
- fabs(input_movevalues[i]));
- */
- }
- }
-
- // TODO CEV this is the wrong place to clear PMF_JUMP_HELD
- if (!(input_buttons & 2))
- self.pmove_flags &= ~PMF_JUMP_HELD;
-
- // figure out the properties of the player's position, then clear timers
- PM_CategorizePosition ();
- PM_ManageTimers (0);
-
- switch (self.movetype)
- {
- case MOVETYPE_WALK:
- local float dogravity, doskim, sticky;
-
- doskim = FALSE;
- sticky = FALSE;
-
- // signal acceleration functions that we're pre-move
- self.pmove_flags |= PMF_PRE_MOVE;
-
- // split the acceleration in two to reduce
- // framerate dependence. -- CEV
- if (self.waterlevel >= WATERLEVEL_WAIST)
- {
- // no gravity, velocity-restoring behavior,
- // or sticky clips underwater -- CEV
- dogravity = FALSE;
- doskim = FALSE;
- sticky = FALSE;
-
- // figure out wishvel -- CEV
- makevectors (input_angles);
- wishvel = v_forward * input_movevalues_x;
- wishvel += v_right * input_movevalues_y;
- wishvel += v_up * input_movevalues_z;
-
- // swim acceleration
- PM_SwimAccelerate (wishvel,
- input_timelength * 0.5f);
- }
- else
- {
- // only yaw matters here -- CEV
- makevectors ([0, input_angles_y, 0]);
- wishvel = v_forward * input_movevalues_x;
- wishvel += v_right * input_movevalues_y;
- // don't need wishvel_z -- CEV
- // wishvel += v_up * input_movevalues_z;
-
- PM_WalkAccelerate (wishvel,
- input_timelength * 0.5f);
-
- // WalkAccelerate calls Jump which might
- // alter pmove_flags, so do our feature
- // checks afterwards -- CEV
- if (self.doublejump_timer <= 0 ||
- self.pmove_flags & PMF_DOUBLEJUMPED ||
- self.pmove_flags & PMF_WALLJUMPED)
- // don't stick to the floor
- sticky = FALSE;
- else
- // we've jumped & haven't doublejumped,
- // so do sticky steps -- CEV
- sticky = TRUE;
-
- // apply gravity only when in the air or on
- // a ramp -- CEV
- if (self.groundnormal &&
- self.groundnormal_z < 1.0f)
- dogravity = TRUE;
- else if (self.pmove_flags & PMF_ONGROUND)
- dogravity = FALSE;
- else
- dogravity = TRUE;
-
- // skim / wallclipping checks -- CEV
- if (self.doublejump_timer >
- (PM_DOUBLEJUMP_WINDOW -
- PM_WALLCLIP_WINDOW) &&
- !(self.pmove_flags & PMF_WALLJUMPED) &&
- self.teleport_time <= (time - 0.1))
- doskim = TRUE;
-
- if (self.pmove_flags & PMF_ONLADDER)
- {
- // feature set for ladders -- CEV
- dogravity = FALSE;
- doskim = FALSE;
- sticky = FALSE;
- }
- }
-
- // timers (part 1) -- CEV
- PM_ManageTimers (input_timelength * 0.5f);
-
- // Do the move. Bounce, Rock, Skate, Roll -- CEV
- PM_DanceMove (dogravity, sticky, TRUE, doskim);
-
- // signal accel functions we're post-move
- self.pmove_flags &= ~PMF_PRE_MOVE;
-
- // second pass at acceleration
- if (self.waterlevel >= WATERLEVEL_WAIST)
- PM_SwimAccelerate (wishvel,
- input_timelength * 0.5f);
- else
- PM_WalkAccelerate (wishvel,
- input_timelength * 0.5f);
-
- // timers (part 2) -- CEV
- PM_ManageTimers (input_timelength * 0.5f);
-
- // clear ladder flag -- CEV
- if (self.pmove_flags & PMF_ONLADDER)
- self.pmove_flags &= ~PMF_ONLADDER;
- break;
-
- case MOVETYPE_FLY:
- // split acceleration in two to reduce framerate
- // dependence. -- CEV
- makevectors (input_angles);
- wishvel = v_forward * input_movevalues_x;
- wishvel += v_right * input_movevalues_y;
- wishvel += v_up * input_movevalues_z;
-
- PM_NoClipAccelerate (wishvel, 1.0f,
- input_timelength * 0.5f);
- PM_DanceMove (FALSE, TRUE, TRUE, FALSE);
- PM_NoClipAccelerate (wishvel, 1.0f,
- input_timelength * 0.5f);
- break;
-
- case MOVETYPE_NOCLIP:
- // noclip is a debugging feature, no need to
- // worry about acceleration consistency. -- CEV
- makevectors (input_angles);
- wishvel = v_forward * input_movevalues_x;
- wishvel += v_right * input_movevalues_y;
- wishvel += v_up * input_movevalues_z;
-
- PM_NoClipAccelerate (wishvel, 1.0f, input_timelength);
- // we're noclipping so update origin directly -- CEV
- self.origin += self.velocity * input_timelength;
- break;
-
- case MOVETYPE_NONE:
- break;
- }
-
- // make sure we've touched the ground entity (it might've slipped
- // through the slidemove above) -- CEV
- if (self.groundentity && self.groundentity.touch != __NULL__)
- PM_DoTouch (self.groundentity);
-
- touchtriggers ();
- setorigin (self, self.origin);
- self = oldself;
-};
-
-//==============================================================================
-// Code graveyard below. Saved here for reference purposes. -- CEV
-//==============================================================================
-
-//----------------------------------------------------------------------
-// PM_ClipVelocity
-//----------------------------------------------------------------------
-#if 0
-#define STOP_EPSILON 0.125
-vector(vector vel, vector normal, float ob, float oneside) PM_ClipVelocity =
-{
- local float backoff;
-
- backoff = vel * normal;
-
- if (backoff < 0)
- backoff *= ob;
- else
- if (oneside)
- // backoff = 0;
- backoff *= -0.001;
- else
- backoff /= ob;
-
- vel -= normal * backoff;
-
- if (vel_x > -STOP_EPSILON && vel_x < STOP_EPSILON)
- vel_x = 0;
- if (vel_y > -STOP_EPSILON && vel_y < STOP_EPSILON)
- vel_y = 0;
- if (vel_z > -STOP_EPSILON && vel_z < STOP_EPSILON)
- vel_z = 0;
-
- return vel;
-};
-#endif
-
-//----------------------------------------------------------------------
-// PM_Q3SlideMove
-//
-// Based on Quake 3's PM_SlideMove (found in the Quake III engine GPL2
-// source release, file bg_slidemove.c). This doesn't work reliably for
-// reasons that are unclear to me; I would guess it has to do with its
-// complex use of an array. I've left it here commented out for reference
-// purposes. -- CEV
-//----------------------------------------------------------------------
-#if 0
-int(float dogravity) PM_Q3SlideMove =
-{
- vector planes[PHYS_SLIDE_MAX_CLIP_PLANES];
- vector dir, end, new_v, start_v;
- vector grav_v, gnew_v;
- int blocked, bumpcount, numplanes, i, j, k;
- float d, time_left, ent_grav;
-
- blocked = 0;
-
- // initialize all these vectors
- for (i = 0; i < PHYS_SLIDE_MAX_CLIP_PLANES; i++)
- planes[i] = '0 0 0';
- dir = end = new_v = grav_v = gnew_v = '0 0 0';
- start_v = self.velocity;
-
- if (dogravity)
- {
- grav_v = self.velocity;
- if (self.gravity)
- ent_grav = self.gravity;
- else
- ent_grav = 1.0;
- grav_v_z -= ent_grav * cvar("sv_gravity") * input_timelength;
- self.velocity_z = (self.velocity_z + grav_v_z) * 0.5;
- start_v_z = grav_v_z;
- if (self.groundnormal)
- {
- self.velocity = phys_clipvelocity (self.velocity,
- self.groundnormal, PM_OVERCLIP, FALSE);
- }
- }
-
- if (self.groundnormal)
- {
- numplanes = 1;
- planes[0] = self.groundnormal;
- }
- else
- numplanes = 0;
-
- // never turn against original velocity
- planes[numplanes] = normalize (self.velocity);
- numplanes++;
-
- for (bumpcount = 0, time_left = input_timelength;
- time_left > 0 && bumpcount < PHYS_SLIDE_NUMBUMPS; bumpcount++)
- {
- end = self.origin + self.velocity * time_left;
- tracebox(self.origin, self.mins, self.maxs, end, FALSE, self);
-
- if (trace_allsolid || trace_startsolid)
- {
- // entity is trapped in a solid; attempt to nudge out
- if (phys_nudge()) continue;
-
- // nah, we're stuck. don't build up falling damage
- // but allow sideways acceleration
- dprint ("PM_Q3SlideMove: entity trapped in a solid\n");
- self.velocity_z = 0;
- return 3;
- }
-
- float cur_fraction = trace_fraction;
- vector cur_plane = trace_plane_normal;
-
- if (cur_fraction > 0)
- self.origin = trace_endpos;
-
- if (cur_fraction == 1) break;
-
- /*
- // this isn't working for some reason -- CEV
- if (cur_plane.z)
- if (cur_plane.z > 0.7)
- {
- blocked |= 1;
- self.flags |= FL_ONGROUND;
- self.groundnormal = cur_plane;
- self.groundentity = trace_ent;
- }
- else
- blocked |= 2;
- */
-
- phys_dotouch (trace_ent);
- time_left -= time_left * cur_fraction;
-
- if (numplanes >= PHYS_SLIDE_MAX_CLIP_PLANES)
- {
- // this shouldn't really happen
- if (cvar("developer"))
- {
- dprint ("PM_Q3SlideMove: numplanes >= max: ");
- dprint (ftos(numplanes));
- dprint ("\n");
- }
- self.velocity = '0 0 0';
- return 7;
- }
-
- // comment from Q3 source:
- // if this is the same plane we hit before nudge velocity out
- // along it; this fixes some issues with non-axial planes
- for (i = 0; i < numplanes; i++)
- {
- if (cur_plane * planes[i] > 0.99)
- {
- dprint ("PM_Q3SlideMove: non-axial plane\n");
- self.velocity += cur_plane;
- break;
- }
- }
-
- if (i < numplanes) continue;
-
- planes[numplanes] = cur_plane;
- numplanes++;
-
- // modify velocity so it parallels all of the clip planes
- // find a plane that it enters
- for (i = 0; i < numplanes; i++)
- {
- if (self.velocity * planes[i] >= 0.1)
- continue;
-
- // slide along the plane
- new_v = phys_clipvelocity (self.velocity, planes[i],
- PM_OVERCLIP, FALSE);
- if (dogravity)
- gnew_v = phys_clipvelocity (grav_v,
- planes[i], PM_OVERCLIP, FALSE);
-
- for (j = 0; j < numplanes; j++)
- {
- if (new_v * planes[j] >= 0.1) continue;
-
- // try clipping the move to the plane
- new_v = phys_clipvelocity (new_v, planes[j],
- PM_OVERCLIP, FALSE);
- if (dogravity)
- gnew_v = phys_clipvelocity (gnew_v,
- planes[j], PM_OVERCLIP, FALSE);
-
- // see if it goes back into the first clip plane
- if (new_v * planes[i] >= 0) continue;
-
- // slide along the crease
- dir = crossproduct (planes[i], planes[j]);
- dir = normalize (dir);
- d = dir * self.velocity;
- new_v = dir * d;
-
- if (dogravity)
- {
- dir = crossproduct(planes[i],planes[j]);
- dir = normalize (dir);
- d = dir * grav_v;
- gnew_v = dir * d;
- }
-
- // see if the move enters a third plane
- for (k = 0; k < numplanes; k++)
- {
- if (k == i || k == j)
- continue;
-
- if (new_v * planes[k] >= 0.1)
- // no interaction
- continue;
-
- // testing something here -- CEV
- if (numplanes < 3)
- continue;
-
- // stop at a triple plane interaction
- if (cvar("developer"))
- {
- // laugh at my 80 col terminal
- dprint ("PM_Q3SlideMove: ");
- dprint ("triple plane inter");
- dprint ("action; numplanes: ");
- dprint (ftos(numplanes));
- dprint ("\n");
- }
- self.velocity = '0 0 0';
- return 7;
- }
- }
-
- // if we've fixed all interaction try another move
- self.velocity = new_v;
- if (dogravity) grav_v = gnew_v;
- break;
- }
- }
-
- // final gravity check here
- if (dogravity) self.velocity = grav_v;
-
- // wallclip / wall skim timer check
- if ((self.primal_speed > PM_MAXSPEED) &&
- (self.jump_time) &&
- (!(self.flags & FL_WATERJUMP)) &&
- (self.teleport_time <= (time - 0.1)) &&
- (self.boost_time <= time - PM_BOOST_WINDOW) &&
- (self.jump_time > (time - PM_WALLCLIP_WINDOW)) &&
- (vlen(start_v) > vlen(self.velocity)))
- {
- // dprint ("PM_Q3SlideMove: restoring velocity...\n");
- self.velocity = start_v;
- }
-
- if (bumpcount > 0) blocked |= 8;
- return blocked;
-};
-#endif
-
-//----------------------------------------------------------------------
-// PM_Q1FlyMove
-//
-// Based on Quake 1's SV_FlyMove function (found in id's engine, QuakeSpasm,
-// and others). Has the disadvantage of using an array of vectors, and
-// is slow (I assume) in QuakeC. -- CEV
-//----------------------------------------------------------------------
-#if 0
-#define PM_SLIDE_MAX_CLIP_PLANES 5
-#define PM_SLIDE_NUMBUMPS 5
-int(float dogravity, float onesided) PM_Q1FlyMove =
-{
- vector planes[PM_SLIDE_MAX_CLIP_PLANES];
- vector dir, end, new_v, start_v;
- int blocked, bumpcount, numplanes, i, j;
- float d, ent_grav, grav, time_left;
-
- blocked = numplanes = 0;
-
- // initialize all these vectors
- for (i = 0; i < PM_SLIDE_MAX_CLIP_PLANES; i++)
- planes[i] = '0 0 0';
- dir = end = new_v = '0 0 0';
-
- if (dogravity)
- {
- if (self.gravity)
- ent_grav = self.gravity;
- else
- ent_grav = 1.0;
- grav = ent_grav * autocvar(sv_gravity, 800) * input_timelength;
- // we'll do half of it now, half later -- CEV
- self.velocity_z -= grav * 0.5;
- }
-
- // set start_v after gravity check above
- start_v = self.velocity;
-
- for (bumpcount = 0, time_left = input_timelength;
- time_left > 0 && bumpcount < PM_SLIDE_NUMBUMPS; bumpcount++)
- {
- end = self.origin + self.velocity * time_left;
- tracebox (self.origin, self.mins, self.maxs, end, FALSE, self);
-
- if (trace_allsolid || trace_startsolid)
- {
- // entity is trapped in a solid; attempt to nudge out
- if (PM_Nudge())
- continue;
-
- // nah, we're stuck. don't build up falling damage
- // but allow sideways acceleration
- #ifdef SSQC
- dprint ("PM_Q1FlyMove: entity trapped in a solid\n");
- #endif
- self.velocity_z = 0;
- return 3;
- }
-
- if (trace_fraction >= 0.001)
- self.origin = trace_endpos;
-
- if (trace_fraction >= 1.0f)
- break;
-
- if (trace_plane_normal_z > 0.7)
- {
- blocked |= 1;
- self.groundnormal = trace_plane_normal;
- self.groundentity = trace_ent;
- }
-
- if (!(trace_plane_normal_z))
- blocked |= 2;
-
- PM_DoTouch (trace_ent);
- time_left -= time_left * trace_fraction;
-
- if (numplanes >= PM_SLIDE_MAX_CLIP_PLANES)
- {
- // this shouldn't really happen
- if (cvar("developer"))
- {
- #ifdef SSQC
- dprint ("PM_Q1FlyMove: numplanes >= max: ");
- dprint (ftos(numplanes));
- dprint ("\n");
- #endif
- }
- self.velocity = '0 0 0';
- blocked = 7;
- break;
- }
-
- planes[numplanes] = trace_plane_normal;
- numplanes++;
-
- for (i = 0; i < numplanes; i++)
- {
- // slide along the plane
- new_v = PM_ClipVelocity (self.velocity,
- planes[i], PM_OVERCLIP, onesided);
-
- for (j = 0; j < numplanes; j++)
- if (j != i)
- // not ok (the comment says)
- if ((new_v * planes[j]) < 0)
- break;
-
- if (j == numplanes)
- break;
- }
-
- if (i == numplanes)
- {
- if (numplanes != 2)
- {
- #ifdef SSQC
- dprint ("PM_Q1FlyMove: stopping dead\n");
- #endif
- self.velocity = '0 0 0';
- blocked = 7;
- break;
- }
-
- // slide along the crease
- dir = crossproduct (planes[0], planes[1]);
- dir = normalize (dir);
- d = (dir * self.velocity);
- new_v = dir * d;
- }
-
- self.velocity = new_v;
-
- if ((self.velocity * start_v) <= 0)
- {
- #ifdef SSQC
- dprint ("PM_Q1FlyMove: turned against orig vel\n");
- #endif
- self.velocity = '0 0 0';
- break;
- }
- }
-
- // wallclip / wall skim timer check
- if ( // (self.primal_speed > PM_MAXSPEED) &&
- (self.velocity != '0 0 0') &&
- (self.jump_time) &&
- (!(self.pmove_flags & PMF_WATERJUMP)) &&
- (self.teleport_time <= (time - 0.1)) &&
- (self.boost_time <= time - PM_BOOST_WINDOW) &&
- (self.jump_time > (time - PM_WALLCLIP_WINDOW)) &&
- (vlen(start_v) > vlen(self.velocity)))
- {
- #ifdef SSQC
- dprint ("PM_Q1FlyMove: restoring velocity...\n");
- #endif
- self.velocity = [start_v_x, start_v_y, self.velocity_z];
- }
-
- // final gravity check here
- if (dogravity)
- self.velocity_z -= grav * 0.5;
-
- /* for debugging -- CEV
- #ifdef SSQC
- dprint ("PM_Q1FlyMove: numplanes ");
- dprint (ftos(numplanes));
- dprint ("\n");
- #endif
- */
-
- return blocked;
-};
-#endif
-
-//----------------------------------------------------------------------
-// PM_StepSlideMove
-//
-// Based on the StepSlideMove function found in the Quake III sourcecode.
-// Calls PM_Q1FlyMove several times. This works, but is slow and has
-// some tracking issues (probably my fault). -- CEV
-//----------------------------------------------------------------------
-#if 0
-void(float dogravity, float onesided) PM_StepSlideMove =
-{
- vector start_o, start_v, first_o, first_v;
- vector up, down;
- float stepsize;
- int clip, first_clip;
- int start_onground;
-
- clip = first_clip = 0;
- start_o = self.origin;
- start_v = self.velocity;
- start_onground = (self.pmove_flags & PMF_ONGROUND);
-
- // first try let's go
- first_clip = PM_Q1FlyMove (dogravity, onesided);
-
- if (!(first_clip & 2) && !(first_clip & 8))
- {
- // we got where we wanted to go right away
- // #ifdef SSQC
- // dprint ("PM_StepSlideMove: accepting first move\n");
- // #endif
- if (first_clip & 1)
- self.pmove_flags |= PMF_ONGROUND;
- else
- self.pmove_flags &= ~PMF_ONGROUND;
- return;
- }
-
- if (self.movetype != MOVETYPE_WALK)
- // gibbed by a trigger?
- return;
-
- if (autocvar(pm_nostep, FALSE))
- // no stepping. useful for testing -- CEV
- return;
-
- if (!(autocvar(pm_airstep, TRUE)) && !(self.pmove_flags & PMF_ONGROUND))
- // Borrowing FTE's pm_airstep cvar here. If false, don't
- // step up while in the air (changes stairs) -- CEV
- return;
-
- first_o = self.origin;
- first_v = self.velocity;
-
- self.origin = start_o;
- self.velocity = start_v;
-
- up = start_o;
- up_z += PM_STEPHEIGHT;
- tracebox (start_o, self.mins, self.maxs, up, FALSE, self);
-
- if (trace_allsolid)
- {
- #ifdef SSQC
- dprint ("PM_StepSlideMove: can't step up\n");
- #endif
- self.origin = first_o;
- self.velocity = first_v;
- if (first_clip & 1)
- self.pmove_flags |= PMF_ONGROUND;
- else
- self.pmove_flags &= ~PMF_ONGROUND;
- return;
- }
-
- // try slidemove from this position (in air)
- stepsize = trace_endpos_z - start_o_z;
- self.origin = trace_endpos;
- self.velocity = start_v;
- clip = PM_Q1FlyMove (dogravity, onesided);
-
- // push down the final amount
- down = self.origin;
- down_z -= stepsize;
- tracebox (self.origin, self.mins, self.maxs, down, FALSE, self);
-
- if (trace_allsolid)
- {
- #ifdef SSQC
- dprint ("PM_StepSlideMove: second move is in a solid\n");
- #endif
- self.origin = first_o;
- self.velocity = first_v;
- if (first_clip & 1)
- self.pmove_flags |= PMF_ONGROUND;
- else
- self.pmove_flags &= ~PMF_ONGROUND;
- return;
- }
-
- if (!trace_plane_normal_z || trace_plane_normal_z > 0.7)
- {
- // we're on 'good ground', accept the second slidemove
- // #ifdef SSQC
- // dprint ("PM_StepSlideMove: accepting second slidemove\n");
- // #endif
- self.origin = trace_endpos;
- if (trace_fraction < 1.0)
- {
- // clip to step
- self.velocity = PM_ClipVelocity (self.velocity,
- trace_plane_normal, PM_OVERCLIP, onesided);
- }
- if (trace_plane_normal_z > 0.7)
- self.pmove_flags |= PMF_ONGROUND;
- else
- self.pmove_flags &= ~PMF_ONGROUND;
- }
- else
- {
- // not on 'good ground', revert to first slidemove
- // see the similar section of SV_WalkMove
- // #ifdef SSQC
- // dprint ("PM_StepSlideMove: reverting to first move\n");
- // #endif
- self.origin = first_o;
- self.velocity = first_v;
- if (first_clip & 1)
- self.pmove_flags |= PMF_ONGROUND;
- else
- self.pmove_flags &= ~PMF_ONGROUND;
- }
-
- // this is a complicated check.
- // if we started in the air and we're now on the ground
- // and we stepped up and we lost some Z velocity then we've
- // clipped to ground on a step up
- if (!start_onground && (self.pmove_flags & PMF_ONGROUND) &&
- (start_v_z > self.velocity_z) &&
- (self.velocity_z < 1) &&
- (self.origin_z - start_o_z > 0))
- {
- if (!self.boost_time &&
- self.boost_time <= time - PM_BOOST_WINDOW)
- self.boost_time = time;
-
- if (cvar("developer"))
- {
- #ifdef SSQC
- stepsize = self.origin_z - start_o_z;
- dprint (sprintf("PM_StepSlideMove: step up: %g\n",
- stepsize));
- #endif
- }
- }
-};
-#endif
Return to the top of this page or return to the overview of this repo.
Diff qc/pmove.qc
diff --git a/qc/pmove.qc b/qc/pmove.qc
new file mode 100644
index 0000000..15d7286
--- /dev/null
+++ b/qc/pmove.qc
@@ -0,0 +1,2220 @@
+//==============================================================================
+// PMOVE
+//==============================================================================
+
+// TODO CEV: crouching
+// TODO CEV: crouch sliding (useful for sliding up stairs)
+// TODO CEV: crouch-wall-thing (wallrunning? wall sliding?)
+// TODO CEV: improved player unstick function
+// TODO CEV: more work on walking
+// TODO CEV: varied sounds (footsteps, different jump sounds)
+
+//======================================================================
+// globals managed by FTEQW, from fteextensions.qc -- CEV
+//======================================================================
+
+float input_buttons; // buttons pressed by the client
+// float input_impulse;
+float input_timelength; // frame / tic time
+vector input_angles; // +x = DOWN
+vector input_movevalues; // movement requested by client
+
+//======================================================================
+// fields
+//======================================================================
+
+// note: timers are expensive, require synch between server and client -- CEV
+// .entity groundentity;
+.vector groundnormal;
+.float pmove_flags; // custom movement flags -- CEV
+.float doublejump_timer; // time in which a player can doublejump
+.float groundboost_timer; // time to apply low friction -- CEV
+.void() customphysics;
+
+//======================================================================
+// pmove constants (could be reworked as cvars, would add overhead) -- CEV
+//======================================================================
+
+// circle jump calculations (in python, probably wrong on my [CEV's] part):
+// 320 * math.sqrt((A * (2 - A * (1 / T))) / (c * (2 - c * (1 / T))))
+// where A = accel (10.0), c = friction (4.0), T = framerate (q3 125, q1 77?)
+// this equation is from the article "Circle-Jump Theory" by injx, found here:
+// https://www.artifexquake.com/?page_id=184
+//
+// Max ground speed for accel 10, friction 6, T 125, w 320 (vq3) is ~409
+// Max ground speed for accel 15, friction 6, T 125, w 320 (CPM) is ~497
+// accel 10.666, friction 6, T 125, wishspeed 320 = 423
+// accel 10.666, friction 6, T 125, wishspeed 360 = 475
+// accel 10.666, friction 6, T 125, wishspeed 380 = 502
+// accel 10.666, friction 6, T 125, wishspeed 400 = 528
+// accel 11.666, friction 6, T 125, wishspeed 320 = 441
+// accel 11.666, friction 6, T 125, wishspeed 360 = 496
+// accel 11.666, friction 6, T 125, wishspeed 380 = 523
+// accel 15.666, friction 8, T 125, wishspeed 320 = 440
+// accel 15.666, friction 8, T 125, wishspeed 380 = 523
+
+// acceleration & friction (cheers for the number of the beast)
+const float PM_AIRACCEL = 6.666f; // 10 in Q1; now 7.5 or 8.0
+const float PM_AIRACCELQ3 = 0.666f; // 1.0 in Q3 ?; now 0.75 or 0.8
+const float PM_AIRACCELFWD = 0.666; // 1 feels close to Q3 / CPM
+const float PM_AIRACCELBACK = 6.666f; // Air stop speed in Q3? 5.0f?
+const float PM_AIRACCELTURN = 666.0f; // affects +fwd turning radius; 100.0f
+const float PM_BOOSTACCEL = 10.666f; // ground boost accel; 10; 10 + 1.25
+const float PM_BOOSTFRICTION = 6.0f; // ground boost friction; 4 is Q1
+const float PM_GROUNDACCEL = 10.666f; // 10 is Q1, 15 is CPM; 15 - 1.25 13.75
+const float PM_GROUNDFRICTION = 6.0f; // 4 for Q1, 6 for Q3, 8 for (old?) CPM
+const vector PM_GROUNDDIST_V = '0 0 1'; // distance for ground check
+const float PM_WATERACCEL = 10.0f; // water acceleration
+const float PM_WATERFRICTION = 4.0f; // friction in water
+
+// horizontal speeds (mostly)
+const float PM_BOOSTWISHSPEED = 380.0f; //
+const float PM_CROUCHSPEED = 120.0f; // ???
+const float PM_MAXSPEED = 320.0f; // 320 always
+const float PM_MAXAIRSPEED = 30.0f; // 30 for Q1 air control
+const float PM_RUNSPEED = 320.0f; // run speed override; 400.0 default
+const float PM_STOPSPEED = 100.0f;
+const float PM_TELEEXITSPEED = 400.0f; // exit teleporters at this speed
+const float PM_WALKSPEED = 200.0f; // walk speed override
+const float PM_WATERMAXSPEED = 224.0f; // 320 * 0.7
+const float PM_WATERSINKSPEED = 60.0f;
+
+// vertical speeds (mostly)
+const float PM_GRAVITY = 800.0f; // unless sv_gravity, scaled by .gravity
+const float PM_JUMPSPEED = 270.0f; // standard jump Z velocity; 90 * 3
+const float PM_DOUBLEJUMPSPEED = 270.0f;// 270 * 1.5 in CPM; 360 here
+const float PM_STAIRJUMPSPEED = 360.0f; // 360 = 90 * 4
+const float PM_TELEJUMPSPEED = 360.0f; // same as STAIRJUMPSPEED
+const float PM_WALLJUMPFORCE = 90.0f; // 90 * 2; push away from wall
+const float PM_WALLJUMPGROUND = 28.0f; // distance from ground to allow WJ (36)
+const float PM_WALLJUMPLIMIT = -225.f; // no walljump if Z vel below this
+const float PM_WALLJUMPSPEED = 270.0f; // 225 = 90 * 2.5; wall jump
+const float PM_WALLJUMPDOUBLE = 360.0f; // 315 = 90 * 3.5; wall doublejump
+
+// timing
+const float PM_DOUBLEJUMP_WINDOW = 0.4f;// 2 jumps in this time is a double
+const float PM_GROUNDBOOST_WINDOW = 0.4f;// groundboost duration
+const float PM_TELEJUMP_WINDOW = 0.4f; // duration to perform a telejump
+const float PM_WALLJUMP_WINDOW = 0.2f; // duration between walljumps
+const float PM_WALLCLIP_WINDOW = 0.25f; //
+
+// misc
+const float PM_OVERCLIP = 1.0f; // Quake3's OVERCLIP is 1.001f
+const float PM_ONESIDEDCLIP = -0.05; // -0.001, -0.01, -0.1
+const float PM_STEPHEIGHT = 18.0f; // 18 for Q1, 22 for later games?
+const vector PM_TELEDROP = '0 0 -64'; // drop teleporter exit to floor if
+ // floor is within this distance
+// water level
+const int WATERLEVEL_NONE = 0;
+const int WATERLEVEL_FEET = 1;
+const int WATERLEVEL_WAIST = 2;
+const int WATERLEVEL_EYES = 3;
+
+//
+const vector CROUCHED_MINS = '-16 -16 -18';// VEC_HULL_MIN is '-16 -16 -24'
+const vector CROUCHED_MAXS = '16 16 18';// VEC_HULL_MAX is '16 16 32'
+
+// pmove_flags
+enumflags
+{
+ PMF_ONGROUND, // entity is on ground
+ PMF_STARTGROUND, // entity started the move on ground
+ PMF_ONLADDER, // entity is on a ladder
+ PMF_INWATER, // entity is in water
+ PMF_CROUCH_HELD, // player is holding the crouch key
+ PMF_CROUCHED, // entity is crouching
+ PMF_JUMP_HELD, // player is holding the jump key
+ PMF_DOUBLEJUMPED, // entity has doublejumped
+ PMF_WALLJUMPED, // entity has walljumped
+ PMF_WATERJUMPED, // entity has waterjumped
+ PMF_PRE_MOVE // hint that origin hasn't updated yet
+};
+
+// prototypes
+static void(entity ent) PM_DoTouch;
+float() PM_Nudge;
+void(float dogravity, float sticky, float dostep, float doskim) PM_DanceMove;
+void() PM_CategorizePosition;
+void(float friction, float move_time) PM_Friction;
+void(vector wishdir, float wishspeed, float accel, float move_time)
+ PM_Accelerate;
+void(vector wishvel, float wishspeed, float accel, float move_time)
+ PM_AirAccelerate;
+void(vector wishdir, float wishspeed, float move_time) PM_AirControl;
+void() PM_Jump;
+void() PM_WallJump;
+void(vector wishvel, float move_time) PM_WalkAccelerate;
+void(vector wishvel, float move_time) PM_SwimAccelerate;
+void(vector wishvel, float scale, float move_time) PM_NoClipAccelerate;
+void(float move_time) PM_ManageTimers;
+void(entity target) PM_Move;
+
+//----------------------------------------------------------------------
+// PM_DoTouch
+//----------------------------------------------------------------------
+static void(entity ent) PM_DoTouch =
+{
+#ifdef SSQC
+ if (ent && (ent.classgroup & CG_ENTITY))
+ {
+ other = self;
+ ((base_entity)ent).touch ();
+ return;
+ }
+#endif
+ if (ent && ent.touch != __NULL__)
+ {
+ local entity orig_self;
+
+ orig_self = self;
+ other = self;
+ self = ent;
+ self.touch ();
+ self = orig_self;
+ }
+};
+
+//----------------------------------------------------------------------
+// PM_Nudge
+// from the GPL2 CSQCTest code that comes with FTEQW; is called often
+// to nudge player origin due to float/network precision errors -- CEV
+//----------------------------------------------------------------------
+float() PM_Nudge =
+{
+ vector test, org = self.origin;
+
+ // check current position.
+ tracebox (org, self.mins, self.maxs, org, FALSE, self);
+ if (!trace_startsolid)
+ return TRUE;
+
+ // truncate to network accuracy
+ org_x = floor (org_x * 8 + (1.0 / 16)) * 0.125;
+ org_y = floor (org_y * 8 + (1.0 / 16)) * 0.125;
+ org_z = floor (org_z * 8 + (1.0 / 16)) * 0.125;
+
+ test = org;
+
+ static float offsets[] = {0, -1./8, 1./8, -2./8, 2./8};
+ for (float z = 0; z < offsets.length; z++)
+ {
+ test.z = org.z + offsets[z];
+ for (float y = 0; y < offsets.length; y++)
+ {
+ test.y = org.y + offsets[y];
+ for (float x = 0; x < offsets.length; x++)
+ {
+ test.x = org.x + offsets[x];
+ tracebox (test, self.mins, self.maxs, test,
+ FALSE, self);
+ if (!trace_startsolid)
+ {
+ // okay, that'll do
+ self.origin = test;
+ return TRUE;
+ }
+ }
+ }
+ }
+ self.origin = org;
+ return FALSE;
+};
+
+//----------------------------------------------------------------------
+// PM_DanceMove
+//
+// Updates origin according to velocity, moves the player through the world.
+// Same as Q3 SlideMove and Q1 FlyMove. This version handles steps, applies
+// gravity, and restores velocity based on a timer check (those latter two
+// are features of Q3's SlideMove). I've inlined a number of functions
+// (ClipVelocity, DoTouch) to hopefully improve performance.
+//
+// Based on code from the Nuclide SDK (presumably by Eukara), specifically
+// the function PMoveCustom_Move found in the file pmove_custom.qc. This
+// in turn appears to be based on a similar function in the CSQCTest code
+// that comes with FTEQW. -- CEV
+//----------------------------------------------------------------------
+void(float dogravity, float sticky, float dostep, float doskim) PM_DanceMove =
+{
+ vector end, prev_plane, prev_plane2, plane, start_v;
+ float backoff, grav, stepsize, time_left;
+ int i;
+ entity touched_ent;
+
+ // silence some FTEQCC warnings -- CEV
+ end = prev_plane = prev_plane2 = plane = start_v = '0 0 0';
+ backoff = grav = stepsize = time_left = 0;
+
+ if (dogravity)
+ {
+ if (self.gravity)
+ grav = self.gravity;
+ else
+ grav = 1.0;
+ // frame_gravity is set in StartFrame (on the server)
+ // or PlayerUpdate (client) -- CEV
+ grav = grav * frame_gravity * input_timelength;
+ // Half now, half later. Apparently affects framerate
+ // dependence. -- CEV
+ self.velocity_z -= grav * 0.5;
+ }
+
+ start_v = self.velocity;
+
+ // Borrowing FTEQW's pm_airstep cvar here. If false, don't step up
+ // while in the air (changes stairs) -- CEV
+ if (!(frame_airstep) && !(self.pmove_flags & PMF_ONGROUND))
+ dostep = FALSE;
+
+ // no stepping. useful for testing -- CEV
+ if (frame_nostep)
+ dostep = FALSE;
+
+ // we need to bounce off surfaces (in order to slide along them),
+ // so we need at 2 attempts -- comment from the Nuclide SDK
+ // I've changed this to a larger number of attempts (from 3 to 5)
+ // to accommodate more complex plane interactions -- CEV
+ for (i = 5, time_left = input_timelength; time_left > 0 && i; i--)
+ {
+ // set our destination & test the move -- CEV
+ end = self.origin + (self.velocity * time_left);
+ tracebox (self.origin, self.mins, self.maxs, end, FALSE, self);
+
+ if (trace_allsolid || trace_startsolid)
+ {
+ // entity is trapped in a solid; attempt to nudge out
+ if (PM_Nudge())
+ continue;
+
+ // nah, we're stuck. don't build up falling damage
+ // but allow sideways acceleration -- CEV
+ /*
+ #ifdef CSQC
+ dprint ("PM_DanceMove: client ");
+ #endif
+ #ifdef SSQC
+ dprint ("PM_DanceMove: server ");
+ #endif
+ #if defined(CSQC) || defined(SSQC)
+ dprint ("entity trapped in a solid!\n");
+ #endif
+ */
+ self.velocity_z = 0;
+ break;
+ }
+
+ // accept the move -- CEV
+ self.origin = trace_endpos;
+
+ if (trace_fraction >= 1.0f)
+ // no obstructions, made the whole move -- CEV
+ break;
+
+ // zero out stepsize, then store the plane normal and touched
+ // ent for later, then reduce time_left -- CEV
+ stepsize = 0;
+ plane = trace_plane_normal;
+ touched_ent = trace_ent;
+ time_left -= time_left * trace_fraction;
+
+ // integrated StepSlideMove from Nuclide / CSQCTest -- CEV
+ // only attempt to step if there's time left, stepping was
+ // requested, and we hit something like a vertical plane
+ if (dostep && time_left && plane_z >= 0 && plane_z <= 0.7f)
+ {
+ // first: move up
+ trace_endpos = self.origin;
+ trace_endpos_z += PM_STEPHEIGHT;
+ tracebox (self.origin, self.mins, self.maxs,
+ trace_endpos, FALSE, self);
+
+ // don't like having to store another float & vector
+ // but this solves more interactions (ztndm3) -- CEV
+ local float roof_fraction = trace_fraction;
+ local vector roof_plane = trace_plane_normal;
+
+ // second: move forward
+ stepsize = trace_endpos_z - self.origin_z;
+ end = trace_endpos + (self.velocity * time_left);
+ end_z = trace_endpos_z;
+ tracebox (trace_endpos, self.mins, self.maxs, end,
+ FALSE, self);
+
+ // save trace_ent if it has a touch function
+ if (trace_ent && trace_ent.touch != __NULL__)
+ touched_ent = trace_ent;
+
+ if (trace_allsolid || trace_startsolid)
+ {
+ // reject the move immediately -- CEV
+ #ifdef SSQC
+ dprint ("PM_DanceMove: fwd move solid\n");
+ #endif
+ stepsize = 0;
+ self.velocity = '0 0 0';
+ break;
+ }
+ else if (trace_fraction >= 1.0f)
+ {
+ // storing another vector, disappointed in
+ // myself -- CEV
+ local vector fwd_plane = trace_plane_normal;
+
+ // forward move didn't hit anything
+ // third: move down
+ end = trace_endpos;
+ end_z -= stepsize + 1;
+ tracebox (trace_endpos, self.mins, self.maxs,
+ end, FALSE, self);
+
+ if (trace_allsolid || trace_startsolid)
+ {
+ // again reject the move -- CEV
+ #ifdef SSQC
+ dprint ("PM_DanceMove: down move "
+ "solid\n");
+ #endif
+ stepsize = 0;
+ self.velocity = '0 0 0';
+ break;
+ }
+ else if (trace_fraction < 1.0f &&
+ trace_plane_normal_z > 0.7f)
+ {
+ // good ground, accept the move
+ if (roof_fraction < 1.0f &&
+ roof_plane != fwd_plane &&
+ roof_plane != plane)
+ {
+ // do a simple clipvel to the
+ // roof plane right now -- CEV
+ self.velocity -= roof_plane *
+ (self.velocity *
+ roof_plane);
+ }
+
+ stepsize = trace_endpos_z -
+ self.origin_z;
+ self.origin = trace_endpos;
+ time_left -= time_left * trace_fraction;
+
+ prev_plane2 = __NULL__;
+ prev_plane = fwd_plane;
+ plane = trace_plane_normal;
+
+ if (trace_ent &&
+ trace_ent.touch != __NULL__)
+ touched_ent = trace_ent;
+
+ // don't attempt to step again
+ dostep = FALSE;
+ }
+ else
+ {
+ // down move didn't hit and/or
+ // it hit a plane too steep to
+ // be ground -- CEV
+ stepsize = 0;
+ }
+ }
+ else if (trace_plane_normal != plane)
+ {
+ // raised forward move hit something different
+ // than the initial move so clip velocity to
+ // it. solves issues with weird ceilings and
+ // complex movement on stairs. note that we're
+ // not updating origin. -- CEV
+ prev_plane2 = __NULL__;
+ prev_plane = __NULL__;
+ time_left -= time_left * trace_fraction;
+ stepsize = 0;
+
+ if (roof_fraction < 1.0f &&
+ roof_plane != trace_plane_normal)
+ {
+ // save the roof plane & fwd plane
+ prev_plane = roof_plane;
+ plane = trace_plane_normal;
+ }
+ else if (roof_plane == trace_plane_normal)
+ {
+ // roof plane is fwd plane, so save
+ // first and fwd plane
+ prev_plane = plane;
+ plane = trace_plane_normal;
+ }
+ else
+ {
+ // only save fwd plane
+ plane = trace_plane_normal;
+ }
+ }
+ }
+
+ // need to do the ground check & touch the saved ent before
+ // we might stop the loop early -- CEV
+ if (plane_z > 0.7)
+ {
+ if (touched_ent.solid == SOLID_BSP)
+ {
+ self.groundentity = touched_ent;
+ self.groundnormal = plane;
+ self.flags |= FL_ONGROUND;
+ self.pmove_flags |= PMF_ONGROUND;
+ }
+ }
+ else
+ {
+ self.groundentity = __NULL__;
+ self.groundnormal = __NULL__;
+ self.flags &= ~FL_ONGROUND;
+ self.pmove_flags &= ~PMF_ONGROUND;
+ }
+
+ // touch the saved entity; inline PM_DoTouch -- CEV
+ if (touched_ent && touched_ent.touch != __NULL__)
+ {
+ PM_DoTouch (touched_ent);
+ /*
+ local entity orig_self;
+
+ orig_self = self;
+ other = self;
+ self = touched_ent;
+ self.touch ();
+ self = orig_self;
+ */
+ }
+
+ // clip velocity to the saved plane
+ // inline PM_Rebound aka PM_ClipVelocity -- CEV
+ backoff = self.velocity * plane;
+
+ if (backoff < 0)
+ backoff *= PM_OVERCLIP;
+ else
+ if (sticky)
+ backoff /= PM_OVERCLIP;
+ else
+ backoff *= PM_ONESIDEDCLIP;
+
+ self.velocity -= plane * backoff;
+
+ // if velocity interacts with prev_plane then clip to it.
+ // I'm duplicating a little code here (ClipVelocity),
+ // hopefully the audience will forgive me. -- CEV
+ if (prev_plane && prev_plane != plane &&
+ self.velocity * prev_plane < 0)
+ {
+ backoff = self.velocity * prev_plane;
+
+ if (backoff < 0)
+ backoff *= PM_OVERCLIP;
+ else
+ if (sticky)
+ backoff /= PM_OVERCLIP;
+ else
+ backoff *= PM_ONESIDEDCLIP;
+
+ self.velocity -= prev_plane * backoff;
+
+ // Slide along the crease of previous plane and
+ // current plane if the two still interact -- CEV
+ if (self.velocity * plane < 0)
+ {
+ end = crossproduct (prev_plane, plane);
+ end = normalize (end);
+ self.velocity = end * (end * self.velocity);
+ }
+
+ // An optimization from Quake 3 -- CEV
+ if (prev_plane2 && prev_plane2 != plane &&
+ prev_plane2 != prev_plane &&
+ self.velocity * prev_plane2 < 0)
+ {
+ // Stop if we interact with three planes -- CEV
+ #ifdef SSQC
+ dprint ("PM_DanceMove: triple plane stop\n");
+ #endif
+ self.velocity = '0 0 0';
+ break;
+ }
+ }
+
+ // an optimization from Quake 1; is this necessary? -- CEV
+ if ((self.velocity * start_v) <= 0)
+ {
+ // we've turned against original velocity so
+ // clear vel and stop the loop
+ self.velocity = '0 0 0';
+ break;
+ }
+
+ // store current plane and prev_plane for later -- CEV
+ if (prev_plane)
+ prev_plane2 = prev_plane;
+ prev_plane = plane;
+ }
+
+ // wallclip / wall skim timer check
+ // if doskim is true and velocity is non-zero and we lost speed
+ // during the move then restore velocity -- CEV
+ if (doskim && self.velocity && (vlen(start_v) > vlen(self.velocity)))
+ {
+ /*
+ #ifdef SSQC
+ dprint ("PM_DanceMove: wall skim, restoring velocity...\n");
+ #endif
+ */
+ // take the start Z or clipped Z, whichever is lower -- CEV
+ if (start_v_z > self.velocity_z)
+ self.velocity = [start_v_x, start_v_y, self.velocity_z];
+ else
+ self.velocity = start_v;
+ }
+
+ // final gravity check here -- CEV
+ if (dogravity)
+ self.velocity_z -= grav * 0.5;
+
+ // if stepsize is nonzero and we changed from inair to onground then
+ // we've airstepped. this check is here as a placeholder for possible
+ // functionality later -- CEV
+ #ifdef SSQC
+ if (stepsize > 0 && !(self.pmove_flags & PMF_STARTGROUND) &&
+ self.pmove_flags & PMF_ONGROUND)
+ {
+ // more debugging -- CEV
+ dprint (sprintf("PM_DanceMove: airstep: %g\n", stepsize));
+ }
+ #endif
+
+ // a final call to setorigin to update links -- CEV
+ setorigin (self, self.origin);
+
+ /*
+ #ifdef SSQC
+ if (cvar("developer"))
+ // for debugging purposes -- CEV
+ dprint (sprintf("PM_DanceMove: %g bumps\n", 5 - i));
+ #endif
+ */
+};
+
+//----------------------------------------------------------------------
+// PM_CategorizePosition
+// Based on similarly-named function in the GPL2 purecsqc pmove.qc
+//----------------------------------------------------------------------
+void() PM_CategorizePosition =
+{
+ vector point;
+ float contents;
+
+ if (self.movetype == MOVETYPE_NOCLIP || self.movetype == MOVETYPE_FLY)
+ {
+ // noclip is never on ground
+ self.groundentity = __NULL__;
+ self.groundnormal = __NULL__;
+ self.pmove_flags &= ~PMF_DOUBLEJUMPED;
+ self.pmove_flags &= ~PMF_WALLJUMPED;
+ self.pmove_flags &= ~PMF_ONGROUND;
+ self.flags &= ~FL_ONGROUND;
+ }
+ else
+ {
+ // TODO CEV there must be a way to optimize out this
+ // tracebox ground check some of the time
+
+ // do a trace to check for ground
+ tracebox (self.origin, self.mins, self.maxs,
+ self.origin - PM_GROUNDDIST_V, FALSE, self);
+ // only onground if we hit it & it faces upwards
+ if (trace_fraction < 1.0f && trace_plane_normal_z > 0.7f)
+ {
+ // on ground
+ self.groundentity = trace_ent;
+ self.groundnormal = trace_plane_normal;
+ self.flags |= FL_ONGROUND;
+ self.pmove_flags |= PMF_ONGROUND;
+ self.pmove_flags &= ~PMF_WALLJUMPED;
+ }
+ else
+ {
+ // not on ground
+ self.groundentity = __NULL__;
+ self.groundnormal = __NULL__;
+ self.flags &= ~FL_ONGROUND;
+ self.pmove_flags &= ~PMF_ONGROUND;
+ }
+ }
+
+ // check water levels
+ point = self.origin;
+ point_z = self.origin_z + self.mins_z + 1;
+ contents = pointcontents (point);
+ if (contents < CONTENT_SOLID)
+ {
+ self.watertype = contents;
+ point_z = self.origin_z + (self.mins_z + self.maxs_z) * 0.5;
+ if (pointcontents(point) < CONTENT_SOLID)
+ {
+ point_z = self.origin_z + self.maxs_z;
+ if (pointcontents(point) < CONTENT_SOLID)
+ self.waterlevel = WATERLEVEL_EYES;
+ else
+ self.waterlevel = WATERLEVEL_WAIST;
+ }
+ else
+ {
+ self.waterlevel = WATERLEVEL_FEET;
+ }
+ }
+ else
+ {
+ self.watertype = CONTENT_EMPTY;
+ self.waterlevel = WATERLEVEL_NONE;
+ }
+
+ // can't be waterjumping if we're on ground
+ if (self.pmove_flags & PMF_WATERJUMPED &&
+ (self.waterlevel == WATERLEVEL_NONE ||
+ self.pmove_flags & PMF_ONGROUND))
+ {
+ #ifdef SSQC
+ dprint ("PM_CategorizePosition: clearing FL_WATERJUMP\n");
+ #endif
+ self.pmove_flags &= ~PMF_WATERJUMPED;
+ self.flags &= ~FL_WATERJUMP;
+ }
+};
+
+//----------------------------------------------------------------------
+// PM_Friction
+// Ground friction
+//----------------------------------------------------------------------
+void(float friction, float move_time) PM_Friction =
+{
+ float control, newspeed, speed;
+
+ speed = vlen (self.velocity);
+
+ if (speed < 1)
+ {
+ self.velocity = '0 0 0';
+ return;
+ }
+
+ // calculate what their new speed should be
+ control = speed < PM_STOPSPEED ? PM_STOPSPEED : speed;
+ newspeed = speed - control * friction * move_time;
+
+ // and slow them
+ if (newspeed < 0)
+ newspeed = 0;
+
+ self.velocity = self.velocity * (newspeed / speed);
+};
+
+//----------------------------------------------------------------------
+// PM_Accelerate
+// Ground acceleration & Quake 3 style air acceleration -- CEV
+//----------------------------------------------------------------------
+void(vector wishdir, float wishspeed, float accel, float move_time)
+ PM_Accelerate =
+{
+ float newspeed, speed;
+
+ speed = wishspeed - (self.velocity * wishdir);
+
+ if (speed <= 0)
+ return;
+
+ newspeed = accel * move_time * wishspeed;
+ if (newspeed > speed)
+ newspeed = speed;
+
+ self.velocity += newspeed * wishdir;
+};
+
+//----------------------------------------------------------------------
+// PM_AirAccelerate
+// Quake 1 style air acceleration -- CEV
+//----------------------------------------------------------------------
+void(vector wishvel, float wishspeed, float accel, float move_time)
+ PM_AirAccelerate =
+{
+ float newspeed, speed, wishspd;
+
+ // need to ignore Z velocity -- CEV
+ wishvel = [wishvel_x, wishvel_y, 0];
+ wishspd = vlen (wishvel);
+ wishvel = normalize (wishvel);
+ if (wishspd > PM_MAXAIRSPEED)
+ wishspd = PM_MAXAIRSPEED;
+ speed = self.velocity * wishvel;
+ speed = wishspd - speed;
+
+ if (speed <= 0)
+ return;
+
+ newspeed = accel * move_time * wishspeed;
+ if (newspeed > speed)
+ newspeed = speed;
+ self.velocity += newspeed * wishvel;
+};
+
+//----------------------------------------------------------------------
+// PM_AirControl
+// CPM / Painkiller-like Air Control. Based on Xonotic sources. -- CEV
+//----------------------------------------------------------------------
+void(vector wishdir, float wishspeed, float move_time) PM_AirControl =
+{
+ local float speed, zspeed;
+
+ zspeed = self.velocity_z;
+ self.velocity_z = 0;
+
+ speed = vlen (self.velocity);
+ self.velocity = normalize (self.velocity);
+
+ if ((self.velocity * wishdir) > 0)
+ {
+ self.velocity = normalize (self.velocity * speed +
+ wishdir * PM_AIRACCELTURN);
+ }
+
+ self.velocity *= speed;
+ self.velocity_z = zspeed;
+};
+
+//----------------------------------------------------------------------
+// PM_Jump
+//----------------------------------------------------------------------
+void() PM_Jump =
+{
+ // are we already waterjumping, or is jump being held?
+ if (self.pmove_flags & PMF_WATERJUMPED ||
+ self.pmove_flags & PMF_JUMP_HELD)
+ return;
+
+ #ifdef SSQC
+ local string msg = "";
+ #endif
+
+ // make sure we get at least jumpspeed upwards from
+ // the ground plane by clamping it first.
+ if (self.groundnormal && (self.velocity * self.groundnormal < 0))
+ {
+ // #ifdef SSQC
+ // dprint("PM_Jump: clamping to ground\n");
+ // #endif
+ self.velocity -= self.groundnormal *
+ (self.velocity * self.groundnormal);
+ }
+
+ // make sure we get at least the indicated jump speed
+ // this changes the behavior of downward ramps -- CEV
+ if (self.velocity_z < 0)
+ self.velocity_z = 0;
+
+ if (self.doublejump_timer > 0)
+ {
+ // it may be useful in the future (for a tricks mode, etc)
+ // to distinguish between different jump types -- CEV
+ if (self.teleport_time > time - (PM_TELEJUMP_WINDOW + 0.2))
+ {
+ // a teleport jump: allow a larger (+0.2) window to
+ // account for time to travel thru teleporter -- CEV
+ #ifdef SSQC
+ msg = sprintf ("PM_Jump: telejump %g, ",
+ self.velocity_z);
+ #endif
+ // non-additive jump, though it shouldn't matter -- CEV
+ self.velocity_z = PM_TELEJUMPSPEED;
+ }
+ else if (self.groundnormal && self.groundnormal_z == 1 &&
+ self.groundboost_timer > 0)
+ {
+ #ifdef SSQC
+ msg = sprintf ("PM_Jump: stairjump %g, ",
+ self.velocity_z);
+ #endif
+ // don't do additive stairjumps on flat ground -- CEV
+ self.velocity_z = PM_STAIRJUMPSPEED;
+ }
+ else
+ {
+ #ifdef SSQC
+ msg = sprintf ("PM_Jump: doublejump %g, ",
+ self.velocity_z);
+ #endif
+ // the groundnormal might be weird - some kind of
+ // ramp - so we want an additive doublejump here -- CEV
+ self.velocity_z += PM_DOUBLEJUMPSPEED;
+ }
+
+ // set the doublejump flag -- CEV
+ self.pmove_flags |= PMF_DOUBLEJUMPED;
+ }
+ else
+ {
+ // normal jump
+ #ifdef SSQC
+ if (self.velocity_z > 0)
+ msg = sprintf ("PM_Jump: jump %g, ", self.velocity_z);
+ #endif
+
+ // do an additive jump on non-flat ground -- CEV
+ if (self.groundnormal_z == 1)
+ self.velocity_z = PM_JUMPSPEED;
+ else
+ self.velocity_z += PM_JUMPSPEED;
+ }
+
+ // report new Z velocity
+ #ifdef SSQC
+ if (msg != "")
+ dprint (sprintf("%s %g\n", msg, self.velocity_z));
+ #endif
+
+ // manage flags -- CEV
+ self.groundentity = __NULL__;
+ self.groundnormal = __NULL__;
+ self.pmove_flags &= ~PMF_ONGROUND;
+ self.flags &= ~FL_ONGROUND;
+ self.pmove_flags |= PMF_JUMP_HELD;
+ self.button2 = 0;
+ #ifdef SSQC
+ // player jumping sound; copied into pmove from client.qc -- CEV
+ sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
+ #endif
+
+ // timers for all jumps -- CEV
+ self.doublejump_timer = PM_DOUBLEJUMP_WINDOW;
+ self.groundboost_timer = PM_GROUNDBOOST_WINDOW;
+};
+
+//----------------------------------------------------------------------
+// PM_WallJump
+//----------------------------------------------------------------------
+void() PM_WallJump =
+{
+ // are we in water, already waterjumping, already walljumping,
+ // or is jump being held?
+ if (self.waterlevel > WATERLEVEL_NONE ||
+ self.pmove_flags & PMF_WATERJUMPED ||
+ self.pmove_flags & PMF_JUMP_HELD ||
+ self.pmove_flags & PMF_WALLJUMPED)
+ {
+ /*
+ #ifdef SSQC
+ dprint ("PM_WallJump: returning in first block\n");
+ #endif
+ */
+ return;
+ }
+
+ // mandatory interval between jump and walljump
+ if (self.doublejump_timer > (PM_DOUBLEJUMP_WINDOW - PM_WALLJUMP_WINDOW))
+ {
+ /*
+ #ifdef SSQC
+ dprint ("PM_WallJump: returning, interval\n");
+ #endif
+ */
+ return;
+ }
+
+ if (self.velocity_z < PM_WALLJUMPLIMIT)
+ {
+ // falling too fast to walljump
+ // TODO CEV it would be a good idea to include a sound here.
+ /*
+ #ifdef SSQC
+ dprint ("PM_WallJump: falling too fast, returning\n");
+ #endif
+ */
+ return;
+ }
+
+ // minimum distance from ground to walljump
+ local vector end = self.origin;
+ end_z -= PM_WALLJUMPGROUND;
+ tracebox (self.origin, self.mins, self.maxs, end, TRUE, self);
+
+ if (trace_fraction < 1.0f)
+ {
+ /*
+ #ifdef SSQC
+ dprint ("PM_WallJump: too close to ground to walljump\n");
+ #endif
+ */
+ return;
+ }
+
+ // start at STEPHEIGHT + 1 to try and clear any steps -- CEV
+ local vector start;
+ start = self.origin;
+ start_z += PM_STEPHEIGHT + 1;
+ end = start;
+
+ for (int i = 0; i < 4; i++)
+ {
+ // I've borrowed a little logic from Quake Champions Classic
+ // here, shoutout to RhapsodyInGeek, check out their good work
+ // https://github.com/RhapsodyInGeek/Quake-Champions-Classic
+ // v_forward and v_right should still correspond to the
+ // makevectors call from PM_Move -- CEV
+ if (i < 2)
+ if (input_movevalues_x == 0)
+ continue;
+ else
+ end = v_forward * 10;
+ if (i > 1)
+ if (input_movevalues_y == 0)
+ continue;
+ else
+ end = v_right * 10;
+ if (i == 1 || i == 3)
+ end = end - end * 2;
+
+ end = start + end;
+
+ // this ends up firing *a lot* when hopping through a map
+ // normally, unfortunately. traceline may be better here -- CEV
+ tracebox (start, self.mins, self.maxs, end, TRUE, self);
+
+ // in order: we hit something, that something is vaguely
+ // vertical, we hit it at a speed greater than -90, and
+ // that something is within 20 (units?) -- CEV
+ if (trace_fraction < 1.0f &&
+ trace_plane_normal_z <= 0.7f &&
+ trace_plane_normal_z >= 0 &&
+ self.velocity * trace_plane_normal >= -90 &&
+ vlen(self.origin - trace_endpos) <= 20)
+ {
+ self.pmove_flags |= PMF_WALLJUMPED;
+ break;
+ }
+ }
+
+ if (self.pmove_flags & PMF_WALLJUMPED)
+ {
+ // bounce off the wall plane -- CEV
+ self.velocity_x += trace_plane_normal_x * PM_WALLJUMPFORCE;
+ self.velocity_y += trace_plane_normal_y * PM_WALLJUMPFORCE;
+
+ // zero out negative Z, quarter positive Z -- CEV
+ if (self.velocity_z < 0)
+ self.velocity_z = 0;
+ else if (self.velocity_z > 0)
+ self.velocity_z *= 0.25;
+
+ if (self.doublejump_timer > 0)
+ {
+ #ifdef SSQC
+ dprint ("PM_WallJump: wall double ");
+ #endif
+ self.velocity_z += PM_WALLJUMPDOUBLE;
+ }
+ else
+ {
+ #ifdef SSQC
+ dprint ("PM_WallJump: walljump ");
+ #endif
+ self.velocity_z += PM_WALLJUMPSPEED;
+ }
+
+ // manage flags & fields; PMF_WALLJUMPED is already set -- CEV
+ self.pmove_flags |= PMF_JUMP_HELD;
+ self.doublejump_timer = PM_DOUBLEJUMP_WINDOW;
+
+ // server-side stuff
+ #ifdef SSQC
+ dprint (sprintf("dist %g, normalspeed %g\n",
+ vlen(self.origin - trace_endpos),
+ self.velocity * trace_plane_normal));
+ self.button2 = 0;
+ sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
+ #endif
+ }
+};
+
+//----------------------------------------------------------------------
+// PM_WalkAccelerate
+// Handle accel & friction for MOVETYPE_WALK entities (players). -- CEV
+//----------------------------------------------------------------------
+void(vector wishvel, float move_time) PM_WalkAccelerate =
+{
+ vector wishdir;
+ float accel, friction, newspeed, speed, temp, wishspeed;
+
+ accel = friction = temp = 0;
+
+ wishspeed = vlen (wishvel);
+ wishdir = normalize (wishvel);
+
+ if (self.pmove_flags & PMF_PRE_MOVE)
+ {
+ if (self.pmove_flags & PMF_ONLADDER)
+ {
+ // ladder physics
+ // these currently stutter in high ping (or low netfps)
+ // situations because we rely on touch()ing the ladder
+ // trigger to set PMF_ONLADDER and the client doesn't
+ // know about the trigger brush yet -- TODO CEV
+ self.velocity = 0.75 * self.velocity;
+
+ if (input_buttons & 2 || self.button2 > 0 ||
+ input_movevalues_z > 0)
+ {
+ // PlayerClimb -- johnfitz
+ self.velocity_z = 160;
+ }
+ else if (input_movevalues_z < 0)
+ {
+ // PlayerClimbDown -- CEV
+ self.velocity_z = -160;
+ }
+ else
+ {
+ self.flags |= FL_JUMPRELEASED;
+ self.pmove_flags &= ~PMF_JUMP_HELD;
+ self.velocity_z = 0;
+ }
+
+ self.pmove_flags &= ~PMF_ONGROUND;
+ }
+ else
+ {
+ if (input_buttons & 2 || self.button2 > 0 ||
+ input_movevalues_z > 0)
+ {
+ // +jump was pressed
+ if (self.pmove_flags & PMF_ONGROUND)
+ {
+ // normal jump
+ PM_Jump ();
+ }
+ // TODO CEV
+ /*
+ else if (autocvar(pm_walljump, FALSE))
+ */
+ else
+ {
+ // borrow FTE's pm_walljump cvar -- CEV
+ PM_WallJump ();
+ }
+ }
+ else
+ {
+ self.flags |= FL_JUMPRELEASED;
+ }
+ }
+
+ if (self.pmove_flags & PMF_ONGROUND)
+ self.pmove_flags |= PMF_STARTGROUND;
+ else
+ self.pmove_flags &= ~PMF_STARTGROUND;
+ }
+
+ // Test STARTGROUND (the ONGROUND status post jump) to avoid
+ // a ground friction frame when chaining jumps together.
+ // Probably has unintended consequences. -- CEV
+ if (self.pmove_flags & PMF_STARTGROUND)
+ {
+ // we're on ground so pick accel and friction values -- CEV
+ accel = PM_GROUNDACCEL;
+ friction = PM_GROUNDFRICTION;
+
+ if (self.groundboost_timer > 0)
+ {
+ /*
+ accel = PM_BOOSTACCEL;
+ friction = PM_BOOSTFRICTION;
+ */
+ if (wishspeed > PM_BOOSTWISHSPEED)
+ wishspeed = PM_BOOSTWISHSPEED;
+ /*
+ // 320 + (-1 * ([0.x...0.4] - 0.4) * 250)
+ temp = PM_MAXSPEED +
+ (-1 * (self.groundboost_timer - 0.4) * 250);
+ if (wishspeed > temp)
+ wishspeed = temp;
+
+ #ifdef SSQC
+ dprint (sprintf("PM_WalkAccelerate: temp %f\n", temp));
+ #endif
+ */
+ }
+ else
+ {
+ /*
+ accel = PM_GROUNDACCEL;
+ friction = PM_GROUNDFRICTION;
+ */
+ if (wishspeed > PM_MAXSPEED)
+ wishspeed = PM_MAXSPEED;
+ }
+ }
+ else if (input_movevalues_x == 0)
+ {
+ // Q1 air accel when requesting sideways movement in the air
+ // flag a check below with this -1 -- CEV
+ if (wishspeed > PM_MAXSPEED)
+ wishspeed = PM_MAXSPEED;
+
+ accel = -1;
+ }
+ else
+ {
+ if (wishspeed > PM_MAXSPEED)
+ wishspeed = PM_MAXSPEED;
+
+ if (input_movevalues_y == 0)
+ {
+ // Painkiller style air control
+ if (wishvel * self.velocity < 0)
+ // against original velocity; we're slowing down
+ accel = PM_AIRACCELBACK;
+ else
+ // we're with original velocity - gaining speed
+ accel = PM_AIRACCELFWD;
+
+ // borrow the friction var to flag a conditional below
+ friction = -1;
+ }
+ else
+ {
+ // we're in the air and the player is requesting both
+ // forward/back and sideways movement, so pick the Q3
+ // air accel value -- CEV
+ accel = PM_AIRACCELQ3;
+ }
+ }
+
+ // I've duplicated a fair amount of code below, inlining the various
+ // acceleration functions to hopefully improve performance -- CEV
+
+ // apply friction (ground or otherwise)
+ if (friction > 0)
+ {
+ // inline PM_Friction
+ speed = vlen (self.velocity);
+
+ if (speed < 1)
+ {
+ self.velocity = '0 0 0';
+ }
+ else
+ {
+ // calculate what their new speed should be
+ temp = speed < PM_STOPSPEED ? PM_STOPSPEED : speed;
+ newspeed = speed - temp * friction * move_time;
+
+ // and slow them
+ if (newspeed < 0)
+ newspeed = 0;
+
+ self.velocity = self.velocity * (newspeed / speed);
+ }
+ }
+
+ if (accel == -1)
+ {
+ // Quake 1 sideways air acceleration; inline PM_AirAccelerate
+ wishvel_z = 0;
+ temp = vlen (wishvel);
+ wishvel = normalize (wishvel);
+ if (temp > PM_MAXAIRSPEED)
+ temp = PM_MAXAIRSPEED;
+ speed = self.velocity * wishvel;
+ speed = temp - speed;
+
+ if (speed > 0)
+ {
+ newspeed = PM_AIRACCEL * move_time * wishspeed;
+ if (newspeed > speed)
+ newspeed = speed;
+ self.velocity += newspeed * wishvel;
+ }
+ }
+ else if (accel > 0)
+ {
+ // ground & Quake 3 style acceleration; inline PM_Accelerate
+ speed = wishspeed - (self.velocity * wishdir);
+
+ if (speed > 0)
+ {
+ newspeed = accel * move_time * wishspeed;
+ if (newspeed > speed)
+ newspeed = speed;
+
+ self.velocity += newspeed * wishdir;
+ }
+ }
+
+ // CPM & PK-style air control, needs to happen after PM_Accelerate
+ if (friction == -1)
+ {
+ // inline PM_AirControl
+ temp = self.velocity_z;
+ self.velocity_z = 0;
+
+ speed = vlen (self.velocity);
+ self.velocity = normalize (self.velocity);
+
+ if ((self.velocity * wishdir) > 0)
+ {
+ self.velocity = normalize (self.velocity * speed +
+ wishdir * PM_AIRACCELTURN);
+ }
+
+ self.velocity *= speed;
+ self.velocity_z = temp;
+ }
+
+ if (!(self.pmove_flags & PMF_PRE_MOVE))
+ self.pmove_flags &= ~PMF_STARTGROUND;
+};
+
+//----------------------------------------------------------------------
+// PM_SwimAccelerate
+// Largely copied from id Software's WaterMove. Works like NoClipAccelerate.
+//----------------------------------------------------------------------
+void(vector wishvel, float move_time) PM_SwimAccelerate =
+{
+ float wishspeed;
+
+ if (self.pmove_flags & PMF_PRE_MOVE)
+ {
+ // CheckWaterJump
+ if (self.waterlevel == WATERLEVEL_WAIST)
+ {
+ local vector start, end;
+
+ start = self.origin;
+ start_z = start_z + 8;
+ // use wishvel instead of v_forward -- CEV
+ end = [wishvel_x, wishvel_y, 0];
+ end = normalize (end);
+ traceline (start, (start + end * 24), TRUE, self);
+
+ if (trace_fraction < 1)
+ {
+ // solid at the waist
+ start_z = start_z + self.maxs_z - 8;
+ self.movedir = trace_plane_normal * -50;
+ traceline (start, (start + end * 24),
+ TRUE, self);
+
+ if (trace_fraction == 1)
+ {
+ // open at eye level
+ self.flags |= FL_WATERJUMP;
+ self.pmove_flags |= PMF_WATERJUMPED;
+ self.flags &= ~FL_JUMPRELEASED;
+ self.pmove_flags &= ~PMF_JUMP_HELD;
+ // Z velocity was 225
+ self.velocity_z = PM_JUMPSPEED;
+ // we don't care about the 'safety net'
+ // in this movement set (unlike vanilla)
+ // so don't set teleport_time -- CEV
+ // self.teleport_time = time + 2;
+ }
+ }
+ }
+
+ #ifdef SSQC
+ // functionality copied into pmove from client.qc -- CEV
+ if (self.waterlevel >= WATERLEVEL_WAIST)
+ {
+ if (self.swim_flag < time)
+ {
+ // play swimming sound
+ 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);
+ }
+ }
+ #endif
+ }
+
+ if (input_buttons & 2 && !(self.pmove_flags & PMF_WATERJUMPED))
+ // smartjump
+ wishvel_z = max (PM_MAXSPEED, wishvel_z);
+ else if (input_movevalues == '0 0 0')
+ // drift towards bottom -- CEV
+ wishvel_z -= PM_WATERSINKSPEED;
+
+ wishspeed = vlen (wishvel);
+ if (wishspeed > PM_WATERMAXSPEED)
+ wishspeed = PM_WATERMAXSPEED;
+ wishvel = normalize (wishvel);
+
+ // water friction; reuse PM_Friction with a special constant -- CEV
+ if (!(self.pmove_flags & PMF_WATERJUMPED))
+ PM_Friction (PM_WATERFRICTION, move_time);
+
+ // accelerate; reuse PM_Accelerate with a special constant -- CEV
+ PM_Accelerate (wishvel, wishspeed, PM_WATERACCEL, move_time);
+};
+
+//----------------------------------------------------------------------
+// PM_NoClipAccelerate
+//
+// Basic acceleration for flying / noclipping players. Not suitable for
+// swimming. -- CEV
+//----------------------------------------------------------------------
+void(vector wishvel, float scale, float move_time) PM_NoClipAccelerate =
+{
+ float wishspeed;
+
+ // smartjump
+ if (input_buttons & 2)
+ wishvel_z = max (PM_MAXSPEED, wishvel_z);
+
+ wishspeed = vlen (wishvel) * scale;
+ wishvel = normalize (wishvel);
+
+ PM_Friction (PM_GROUNDFRICTION, move_time);
+ PM_Accelerate (wishvel, wishspeed, PM_GROUNDACCEL, move_time);
+};
+
+//----------------------------------------------------------------------
+void(float move_time) PM_ManageTimers =
+{
+ if (self.doublejump_timer > 0 && move_time > 0)
+ self.doublejump_timer -= move_time;
+ else if (self.doublejump_timer < 0)
+ self.doublejump_timer = 0;
+
+ if (self.doublejump_timer == 0)
+ {
+ self.pmove_flags &= ~PMF_DOUBLEJUMPED;
+ }
+
+ if (self.groundboost_timer > 0 && move_time > 0)
+ self.groundboost_timer -= move_time;
+ else if (self.groundboost_timer < 0)
+ self.groundboost_timer = 0;
+};
+
+//----------------------------------------------------------------------
+// PM_Move -- PMOVE entrypoint -- CEV
+//----------------------------------------------------------------------
+void(entity target) PM_Move =
+{
+ if (input_timelength <= 0)
+ // don't process partial frames -- CEV
+ return;
+
+ vector wishvel;
+ entity oldself;
+
+ oldself = self;
+ self = target;
+
+ // Nudge player's origin if the server is sending low-precision
+ // (16 bit?) player coordinates. This can be fixed by setting
+ // sv_bigcoords to 1 (so the server sends float coords). -- CEV
+ if (!frame_bigcoords)
+ PM_Nudge ();
+
+ // rework user input, copying something like QuakeSpasm's always run
+ // feature here. This turns the +speed button into a hold-to-walk
+ // button when cl_run is 0 (when FTE's always run setting is on).
+ // -- CEV
+ if (frame_clrun == FALSE)
+ {
+ // local float s = 0;
+ for (int i = 0; i < 3; i++)
+ {
+ // this works, it's just commented out to stop calling
+ // autocvar quite so many times. to re-enable change
+ // the check against "PM_RUNSPEED" below to "s" -- CEV
+ /*
+ if (i == 0)
+ s = autocvar (cl_forwardspeed, PM_RUNSPEED);
+ else if (i == 1)
+ s = autocvar (cl_sidespeed, PM_RUNSPEED);
+ else if (i == 2)
+ s = autocvar (cl_upspeed, PM_RUNSPEED);
+ */
+ if (fabs(input_movevalues[i]) > 400.0f)
+ input_movevalues[i] = PM_WALKSPEED *
+ (input_movevalues[i] /
+ fabs(input_movevalues[i]));
+ else if (fabs(input_movevalues[i]) == 400.0f)
+ input_movevalues[i] = PM_RUNSPEED *
+ (input_movevalues[i] /
+ fabs(input_movevalues[i]));
+ // Don't need this, it's already PM_RUNSPEED -- CEV
+ /*
+ else if (input_movevalues[i] != 0)
+ input_movevalues[i] = PM_RUNSPEED *
+ (input_movevalues[i] /
+ fabs(input_movevalues[i]));
+ */
+ }
+ }
+
+ // TODO CEV this is the wrong place to clear PMF_JUMP_HELD
+ if (!(input_buttons & 2))
+ self.pmove_flags &= ~PMF_JUMP_HELD;
+
+ // figure out the properties of the player's position, then clear timers
+ PM_CategorizePosition ();
+ PM_ManageTimers (0);
+
+ switch (self.movetype)
+ {
+ case MOVETYPE_WALK:
+ local float dogravity, doskim, sticky;
+
+ doskim = FALSE;
+ sticky = FALSE;
+
+ // signal acceleration functions that we're pre-move
+ self.pmove_flags |= PMF_PRE_MOVE;
+
+ // split the acceleration in two to reduce
+ // framerate dependence. -- CEV
+ if (self.waterlevel >= WATERLEVEL_WAIST)
+ {
+ // no gravity, velocity-restoring behavior,
+ // or sticky clips underwater -- CEV
+ dogravity = FALSE;
+ doskim = FALSE;
+ sticky = FALSE;
+
+ // figure out wishvel -- CEV
+ makevectors (input_angles);
+ wishvel = v_forward * input_movevalues_x;
+ wishvel += v_right * input_movevalues_y;
+ wishvel += v_up * input_movevalues_z;
+
+ // swim acceleration
+ PM_SwimAccelerate (wishvel,
+ input_timelength * 0.5f);
+ }
+ else
+ {
+ // only yaw matters here -- CEV
+ makevectors ([0, input_angles_y, 0]);
+ wishvel = v_forward * input_movevalues_x;
+ wishvel += v_right * input_movevalues_y;
+ // don't need wishvel_z -- CEV
+ // wishvel += v_up * input_movevalues_z;
+
+ PM_WalkAccelerate (wishvel,
+ input_timelength * 0.5f);
+
+ // WalkAccelerate calls Jump which might
+ // alter pmove_flags, so do our feature
+ // checks afterwards -- CEV
+ if (self.doublejump_timer <= 0 ||
+ self.pmove_flags & PMF_DOUBLEJUMPED ||
+ self.pmove_flags & PMF_WALLJUMPED)
+ // don't stick to the floor
+ sticky = FALSE;
+ else
+ // we've jumped & haven't doublejumped,
+ // so do sticky steps -- CEV
+ sticky = TRUE;
+
+ // apply gravity only when in the air or on
+ // a ramp -- CEV
+ if (self.groundnormal &&
+ self.groundnormal_z < 1.0f)
+ dogravity = TRUE;
+ else if (self.pmove_flags & PMF_ONGROUND)
+ dogravity = FALSE;
+ else
+ dogravity = TRUE;
+
+ // skim / wallclipping checks -- CEV
+ if (self.doublejump_timer >
+ (PM_DOUBLEJUMP_WINDOW -
+ PM_WALLCLIP_WINDOW) &&
+ !(self.pmove_flags & PMF_WALLJUMPED) &&
+ self.teleport_time <= (time - 0.1))
+ doskim = TRUE;
+
+ if (self.pmove_flags & PMF_ONLADDER)
+ {
+ // feature set for ladders -- CEV
+ dogravity = FALSE;
+ doskim = FALSE;
+ sticky = FALSE;
+ }
+ }
+
+ // timers (part 1) -- CEV
+ PM_ManageTimers (input_timelength * 0.5f);
+
+ // Do the move. Bounce, Rock, Skate, Roll -- CEV
+ PM_DanceMove (dogravity, sticky, TRUE, doskim);
+
+ // signal accel functions we're post-move
+ self.pmove_flags &= ~PMF_PRE_MOVE;
+
+ // second pass at acceleration
+ if (self.waterlevel >= WATERLEVEL_WAIST)
+ PM_SwimAccelerate (wishvel,
+ input_timelength * 0.5f);
+ else
+ PM_WalkAccelerate (wishvel,
+ input_timelength * 0.5f);
+
+ // timers (part 2) -- CEV
+ PM_ManageTimers (input_timelength * 0.5f);
+
+ // clear ladder flag -- CEV
+ if (self.pmove_flags & PMF_ONLADDER)
+ self.pmove_flags &= ~PMF_ONLADDER;
+ break;
+
+ case MOVETYPE_FLY:
+ // split acceleration in two to reduce framerate
+ // dependence. -- CEV
+ makevectors (input_angles);
+ wishvel = v_forward * input_movevalues_x;
+ wishvel += v_right * input_movevalues_y;
+ wishvel += v_up * input_movevalues_z;
+
+ PM_NoClipAccelerate (wishvel, 1.0f,
+ input_timelength * 0.5f);
+ PM_DanceMove (FALSE, TRUE, TRUE, FALSE);
+ PM_NoClipAccelerate (wishvel, 1.0f,
+ input_timelength * 0.5f);
+ break;
+
+ case MOVETYPE_NOCLIP:
+ // noclip is a debugging feature, no need to
+ // worry about acceleration consistency. -- CEV
+ makevectors (input_angles);
+ wishvel = v_forward * input_movevalues_x;
+ wishvel += v_right * input_movevalues_y;
+ wishvel += v_up * input_movevalues_z;
+
+ PM_NoClipAccelerate (wishvel, 1.0f, input_timelength);
+ // we're noclipping so update origin directly -- CEV
+ self.origin += self.velocity * input_timelength;
+ break;
+
+ case MOVETYPE_NONE:
+ break;
+ }
+
+ // make sure we've touched the ground entity (it might've slipped
+ // through the slidemove above) -- CEV
+ if (self.groundentity && self.groundentity.touch != __NULL__)
+ PM_DoTouch (self.groundentity);
+
+ touchtriggers ();
+ setorigin (self, self.origin);
+ self = oldself;
+};
+
+//==============================================================================
+// Code graveyard below. Saved here for reference purposes. -- CEV
+//==============================================================================
+
+//----------------------------------------------------------------------
+// PM_ClipVelocity
+//----------------------------------------------------------------------
+#if 0
+#define STOP_EPSILON 0.125
+vector(vector vel, vector normal, float ob, float oneside) PM_ClipVelocity =
+{
+ local float backoff;
+
+ backoff = vel * normal;
+
+ if (backoff < 0)
+ backoff *= ob;
+ else
+ if (oneside)
+ // backoff = 0;
+ backoff *= -0.001;
+ else
+ backoff /= ob;
+
+ vel -= normal * backoff;
+
+ if (vel_x > -STOP_EPSILON && vel_x < STOP_EPSILON)
+ vel_x = 0;
+ if (vel_y > -STOP_EPSILON && vel_y < STOP_EPSILON)
+ vel_y = 0;
+ if (vel_z > -STOP_EPSILON && vel_z < STOP_EPSILON)
+ vel_z = 0;
+
+ return vel;
+};
+#endif
+
+//----------------------------------------------------------------------
+// PM_Q3SlideMove
+//
+// Based on Quake 3's PM_SlideMove (found in the Quake III engine GPL2
+// source release, file bg_slidemove.c). This doesn't work reliably for
+// reasons that are unclear to me; I would guess it has to do with its
+// complex use of an array. I've left it here commented out for reference
+// purposes. -- CEV
+//----------------------------------------------------------------------
+#if 0
+int(float dogravity) PM_Q3SlideMove =
+{
+ vector planes[PHYS_SLIDE_MAX_CLIP_PLANES];
+ vector dir, end, new_v, start_v;
+ vector grav_v, gnew_v;
+ int blocked, bumpcount, numplanes, i, j, k;
+ float d, time_left, ent_grav;
+
+ blocked = 0;
+
+ // initialize all these vectors
+ for (i = 0; i < PHYS_SLIDE_MAX_CLIP_PLANES; i++)
+ planes[i] = '0 0 0';
+ dir = end = new_v = grav_v = gnew_v = '0 0 0';
+ start_v = self.velocity;
+
+ if (dogravity)
+ {
+ grav_v = self.velocity;
+ if (self.gravity)
+ ent_grav = self.gravity;
+ else
+ ent_grav = 1.0;
+ grav_v_z -= ent_grav * cvar("sv_gravity") * input_timelength;
+ self.velocity_z = (self.velocity_z + grav_v_z) * 0.5;
+ start_v_z = grav_v_z;
+ if (self.groundnormal)
+ {
+ self.velocity = phys_clipvelocity (self.velocity,
+ self.groundnormal, PM_OVERCLIP, FALSE);
+ }
+ }
+
+ if (self.groundnormal)
+ {
+ numplanes = 1;
+ planes[0] = self.groundnormal;
+ }
+ else
+ numplanes = 0;
+
+ // never turn against original velocity
+ planes[numplanes] = normalize (self.velocity);
+ numplanes++;
+
+ for (bumpcount = 0, time_left = input_timelength;
+ time_left > 0 && bumpcount < PHYS_SLIDE_NUMBUMPS; bumpcount++)
+ {
+ end = self.origin + self.velocity * time_left;
+ tracebox(self.origin, self.mins, self.maxs, end, FALSE, self);
+
+ if (trace_allsolid || trace_startsolid)
+ {
+ // entity is trapped in a solid; attempt to nudge out
+ if (phys_nudge()) continue;
+
+ // nah, we're stuck. don't build up falling damage
+ // but allow sideways acceleration
+ dprint ("PM_Q3SlideMove: entity trapped in a solid\n");
+ self.velocity_z = 0;
+ return 3;
+ }
+
+ float cur_fraction = trace_fraction;
+ vector cur_plane = trace_plane_normal;
+
+ if (cur_fraction > 0)
+ self.origin = trace_endpos;
+
+ if (cur_fraction == 1) break;
+
+ /*
+ // this isn't working for some reason -- CEV
+ if (cur_plane.z)
+ if (cur_plane.z > 0.7)
+ {
+ blocked |= 1;
+ self.flags |= FL_ONGROUND;
+ self.groundnormal = cur_plane;
+ self.groundentity = trace_ent;
+ }
+ else
+ blocked |= 2;
+ */
+
+ phys_dotouch (trace_ent);
+ time_left -= time_left * cur_fraction;
+
+ if (numplanes >= PHYS_SLIDE_MAX_CLIP_PLANES)
+ {
+ // this shouldn't really happen
+ if (cvar("developer"))
+ {
+ dprint ("PM_Q3SlideMove: numplanes >= max: ");
+ dprint (ftos(numplanes));
+ dprint ("\n");
+ }
+ self.velocity = '0 0 0';
+ return 7;
+ }
+
+ // comment from Q3 source:
+ // if this is the same plane we hit before nudge velocity out
+ // along it; this fixes some issues with non-axial planes
+ for (i = 0; i < numplanes; i++)
+ {
+ if (cur_plane * planes[i] > 0.99)
+ {
+ dprint ("PM_Q3SlideMove: non-axial plane\n");
+ self.velocity += cur_plane;
+ break;
+ }
+ }
+
+ if (i < numplanes) continue;
+
+ planes[numplanes] = cur_plane;
+ numplanes++;
+
+ // modify velocity so it parallels all of the clip planes
+ // find a plane that it enters
+ for (i = 0; i < numplanes; i++)
+ {
+ if (self.velocity * planes[i] >= 0.1)
+ continue;
+
+ // slide along the plane
+ new_v = phys_clipvelocity (self.velocity, planes[i],
+ PM_OVERCLIP, FALSE);
+ if (dogravity)
+ gnew_v = phys_clipvelocity (grav_v,
+ planes[i], PM_OVERCLIP, FALSE);
+
+ for (j = 0; j < numplanes; j++)
+ {
+ if (new_v * planes[j] >= 0.1) continue;
+
+ // try clipping the move to the plane
+ new_v = phys_clipvelocity (new_v, planes[j],
+ PM_OVERCLIP, FALSE);
+ if (dogravity)
+ gnew_v = phys_clipvelocity (gnew_v,
+ planes[j], PM_OVERCLIP, FALSE);
+
+ // see if it goes back into the first clip plane
+ if (new_v * planes[i] >= 0) continue;
+
+ // slide along the crease
+ dir = crossproduct (planes[i], planes[j]);
+ dir = normalize (dir);
+ d = dir * self.velocity;
+ new_v = dir * d;
+
+ if (dogravity)
+ {
+ dir = crossproduct(planes[i],planes[j]);
+ dir = normalize (dir);
+ d = dir * grav_v;
+ gnew_v = dir * d;
+ }
+
+ // see if the move enters a third plane
+ for (k = 0; k < numplanes; k++)
+ {
+ if (k == i || k == j)
+ continue;
+
+ if (new_v * planes[k] >= 0.1)
+ // no interaction
+ continue;
+
+ // testing something here -- CEV
+ if (numplanes < 3)
+ continue;
+
+ // stop at a triple plane interaction
+ if (cvar("developer"))
+ {
+ // laugh at my 80 col terminal
+ dprint ("PM_Q3SlideMove: ");
+ dprint ("triple plane inter");
+ dprint ("action; numplanes: ");
+ dprint (ftos(numplanes));
+ dprint ("\n");
+ }
+ self.velocity = '0 0 0';
+ return 7;
+ }
+ }
+
+ // if we've fixed all interaction try another move
+ self.velocity = new_v;
+ if (dogravity) grav_v = gnew_v;
+ break;
+ }
+ }
+
+ // final gravity check here
+ if (dogravity) self.velocity = grav_v;
+
+ // wallclip / wall skim timer check
+ if ((self.primal_speed > PM_MAXSPEED) &&
+ (self.jump_time) &&
+ (!(self.flags & FL_WATERJUMP)) &&
+ (self.teleport_time <= (time - 0.1)) &&
+ (self.boost_time <= time - PM_BOOST_WINDOW) &&
+ (self.jump_time > (time - PM_WALLCLIP_WINDOW)) &&
+ (vlen(start_v) > vlen(self.velocity)))
+ {
+ // dprint ("PM_Q3SlideMove: restoring velocity...\n");
+ self.velocity = start_v;
+ }
+
+ if (bumpcount > 0) blocked |= 8;
+ return blocked;
+};
+#endif
+
+//----------------------------------------------------------------------
+// PM_Q1FlyMove
+//
+// Based on Quake 1's SV_FlyMove function (found in id's engine, QuakeSpasm,
+// and others). Has the disadvantage of using an array of vectors, and
+// is slow (I assume) in QuakeC. -- CEV
+//----------------------------------------------------------------------
+#if 0
+#define PM_SLIDE_MAX_CLIP_PLANES 5
+#define PM_SLIDE_NUMBUMPS 5
+int(float dogravity, float onesided) PM_Q1FlyMove =
+{
+ vector planes[PM_SLIDE_MAX_CLIP_PLANES];
+ vector dir, end, new_v, start_v;
+ int blocked, bumpcount, numplanes, i, j;
+ float d, ent_grav, grav, time_left;
+
+ blocked = numplanes = 0;
+
+ // initialize all these vectors
+ for (i = 0; i < PM_SLIDE_MAX_CLIP_PLANES; i++)
+ planes[i] = '0 0 0';
+ dir = end = new_v = '0 0 0';
+
+ if (dogravity)
+ {
+ if (self.gravity)
+ ent_grav = self.gravity;
+ else
+ ent_grav = 1.0;
+ grav = ent_grav * autocvar(sv_gravity, 800) * input_timelength;
+ // we'll do half of it now, half later -- CEV
+ self.velocity_z -= grav * 0.5;
+ }
+
+ // set start_v after gravity check above
+ start_v = self.velocity;
+
+ for (bumpcount = 0, time_left = input_timelength;
+ time_left > 0 && bumpcount < PM_SLIDE_NUMBUMPS; bumpcount++)
+ {
+ end = self.origin + self.velocity * time_left;
+ tracebox (self.origin, self.mins, self.maxs, end, FALSE, self);
+
+ if (trace_allsolid || trace_startsolid)
+ {
+ // entity is trapped in a solid; attempt to nudge out
+ if (PM_Nudge())
+ continue;
+
+ // nah, we're stuck. don't build up falling damage
+ // but allow sideways acceleration
+ #ifdef SSQC
+ dprint ("PM_Q1FlyMove: entity trapped in a solid\n");
+ #endif
+ self.velocity_z = 0;
+ return 3;
+ }
+
+ if (trace_fraction >= 0.001)
+ self.origin = trace_endpos;
+
+ if (trace_fraction >= 1.0f)
+ break;
+
+ if (trace_plane_normal_z > 0.7)
+ {
+ blocked |= 1;
+ self.groundnormal = trace_plane_normal;
+ self.groundentity = trace_ent;
+ }
+
+ if (!(trace_plane_normal_z))
+ blocked |= 2;
+
+ PM_DoTouch (trace_ent);
+ time_left -= time_left * trace_fraction;
+
+ if (numplanes >= PM_SLIDE_MAX_CLIP_PLANES)
+ {
+ // this shouldn't really happen
+ if (cvar("developer"))
+ {
+ #ifdef SSQC
+ dprint ("PM_Q1FlyMove: numplanes >= max: ");
+ dprint (ftos(numplanes));
+ dprint ("\n");
+ #endif
+ }
+ self.velocity = '0 0 0';
+ blocked = 7;
+ break;
+ }
+
+ planes[numplanes] = trace_plane_normal;
+ numplanes++;
+
+ for (i = 0; i < numplanes; i++)
+ {
+ // slide along the plane
+ new_v = PM_ClipVelocity (self.velocity,
+ planes[i], PM_OVERCLIP, onesided);
+
+ for (j = 0; j < numplanes; j++)
+ if (j != i)
+ // not ok (the comment says)
+ if ((new_v * planes[j]) < 0)
+ break;
+
+ if (j == numplanes)
+ break;
+ }
+
+ if (i == numplanes)
+ {
+ if (numplanes != 2)
+ {
+ #ifdef SSQC
+ dprint ("PM_Q1FlyMove: stopping dead\n");
+ #endif
+ self.velocity = '0 0 0';
+ blocked = 7;
+ break;
+ }
+
+ // slide along the crease
+ dir = crossproduct (planes[0], planes[1]);
+ dir = normalize (dir);
+ d = (dir * self.velocity);
+ new_v = dir * d;
+ }
+
+ self.velocity = new_v;
+
+ if ((self.velocity * start_v) <= 0)
+ {
+ #ifdef SSQC
+ dprint ("PM_Q1FlyMove: turned against orig vel\n");
+ #endif
+ self.velocity = '0 0 0';
+ break;
+ }
+ }
+
+ // wallclip / wall skim timer check
+ if ( // (self.primal_speed > PM_MAXSPEED) &&
+ (self.velocity != '0 0 0') &&
+ (self.jump_time) &&
+ (!(self.pmove_flags & PMF_WATERJUMP)) &&
+ (self.teleport_time <= (time - 0.1)) &&
+ (self.boost_time <= time - PM_BOOST_WINDOW) &&
+ (self.jump_time > (time - PM_WALLCLIP_WINDOW)) &&
+ (vlen(start_v) > vlen(self.velocity)))
+ {
+ #ifdef SSQC
+ dprint ("PM_Q1FlyMove: restoring velocity...\n");
+ #endif
+ self.velocity = [start_v_x, start_v_y, self.velocity_z];
+ }
+
+ // final gravity check here
+ if (dogravity)
+ self.velocity_z -= grav * 0.5;
+
+ /* for debugging -- CEV
+ #ifdef SSQC
+ dprint ("PM_Q1FlyMove: numplanes ");
+ dprint (ftos(numplanes));
+ dprint ("\n");
+ #endif
+ */
+
+ return blocked;
+};
+#endif
+
+//----------------------------------------------------------------------
+// PM_StepSlideMove
+//
+// Based on the StepSlideMove function found in the Quake III sourcecode.
+// Calls PM_Q1FlyMove several times. This works, but is slow and has
+// some tracking issues (probably my fault). -- CEV
+//----------------------------------------------------------------------
+#if 0
+void(float dogravity, float onesided) PM_StepSlideMove =
+{
+ vector start_o, start_v, first_o, first_v;
+ vector up, down;
+ float stepsize;
+ int clip, first_clip;
+ int start_onground;
+
+ clip = first_clip = 0;
+ start_o = self.origin;
+ start_v = self.velocity;
+ start_onground = (self.pmove_flags & PMF_ONGROUND);
+
+ // first try let's go
+ first_clip = PM_Q1FlyMove (dogravity, onesided);
+
+ if (!(first_clip & 2) && !(first_clip & 8))
+ {
+ // we got where we wanted to go right away
+ // #ifdef SSQC
+ // dprint ("PM_StepSlideMove: accepting first move\n");
+ // #endif
+ if (first_clip & 1)
+ self.pmove_flags |= PMF_ONGROUND;
+ else
+ self.pmove_flags &= ~PMF_ONGROUND;
+ return;
+ }
+
+ if (self.movetype != MOVETYPE_WALK)
+ // gibbed by a trigger?
+ return;
+
+ if (autocvar(pm_nostep, FALSE))
+ // no stepping. useful for testing -- CEV
+ return;
+
+ if (!(autocvar(pm_airstep, TRUE)) && !(self.pmove_flags & PMF_ONGROUND))
+ // Borrowing FTE's pm_airstep cvar here. If false, don't
+ // step up while in the air (changes stairs) -- CEV
+ return;
+
+ first_o = self.origin;
+ first_v = self.velocity;
+
+ self.origin = start_o;
+ self.velocity = start_v;
+
+ up = start_o;
+ up_z += PM_STEPHEIGHT;
+ tracebox (start_o, self.mins, self.maxs, up, FALSE, self);
+
+ if (trace_allsolid)
+ {
+ #ifdef SSQC
+ dprint ("PM_StepSlideMove: can't step up\n");
+ #endif
+ self.origin = first_o;
+ self.velocity = first_v;
+ if (first_clip & 1)
+ self.pmove_flags |= PMF_ONGROUND;
+ else
+ self.pmove_flags &= ~PMF_ONGROUND;
+ return;
+ }
+
+ // try slidemove from this position (in air)
+ stepsize = trace_endpos_z - start_o_z;
+ self.origin = trace_endpos;
+ self.velocity = start_v;
+ clip = PM_Q1FlyMove (dogravity, onesided);
+
+ // push down the final amount
+ down = self.origin;
+ down_z -= stepsize;
+ tracebox (self.origin, self.mins, self.maxs, down, FALSE, self);
+
+ if (trace_allsolid)
+ {
+ #ifdef SSQC
+ dprint ("PM_StepSlideMove: second move is in a solid\n");
+ #endif
+ self.origin = first_o;
+ self.velocity = first_v;
+ if (first_clip & 1)
+ self.pmove_flags |= PMF_ONGROUND;
+ else
+ self.pmove_flags &= ~PMF_ONGROUND;
+ return;
+ }
+
+ if (!trace_plane_normal_z || trace_plane_normal_z > 0.7)
+ {
+ // we're on 'good ground', accept the second slidemove
+ // #ifdef SSQC
+ // dprint ("PM_StepSlideMove: accepting second slidemove\n");
+ // #endif
+ self.origin = trace_endpos;
+ if (trace_fraction < 1.0)
+ {
+ // clip to step
+ self.velocity = PM_ClipVelocity (self.velocity,
+ trace_plane_normal, PM_OVERCLIP, onesided);
+ }
+ if (trace_plane_normal_z > 0.7)
+ self.pmove_flags |= PMF_ONGROUND;
+ else
+ self.pmove_flags &= ~PMF_ONGROUND;
+ }
+ else
+ {
+ // not on 'good ground', revert to first slidemove
+ // see the similar section of SV_WalkMove
+ // #ifdef SSQC
+ // dprint ("PM_StepSlideMove: reverting to first move\n");
+ // #endif
+ self.origin = first_o;
+ self.velocity = first_v;
+ if (first_clip & 1)
+ self.pmove_flags |= PMF_ONGROUND;
+ else
+ self.pmove_flags &= ~PMF_ONGROUND;
+ }
+
+ // this is a complicated check.
+ // if we started in the air and we're now on the ground
+ // and we stepped up and we lost some Z velocity then we've
+ // clipped to ground on a step up
+ if (!start_onground && (self.pmove_flags & PMF_ONGROUND) &&
+ (start_v_z > self.velocity_z) &&
+ (self.velocity_z < 1) &&
+ (self.origin_z - start_o_z > 0))
+ {
+ if (!self.boost_time &&
+ self.boost_time <= time - PM_BOOST_WINDOW)
+ self.boost_time = time;
+
+ if (cvar("developer"))
+ {
+ #ifdef SSQC
+ stepsize = self.origin_z - start_o_z;
+ dprint (sprintf("PM_StepSlideMove: step up: %g\n",
+ stepsize));
+ #endif
+ }
+ }
+};
+#endif
Return to the top of this page or return to the overview of this repo.
Diff qc/progs.src
diff --git a/qc/progs.src b/qc/progs.src
index 7fa428d..dac8e6f 100644
--- a/qc/progs.src
+++ b/qc/progs.src
@@ -9,213 +9,205 @@
//----------------------------------------------------------------------
// defs
//----------------------------------------------------------------------
-defs_globalvars.qc // globalvars_t
-defs_entvars.qc // entvars_t
-defs_builtins.qc // builtin functions (& overrides)
-defs_misc.qc // additional
-defs_classtype.qc // global class list
+defs_globalvars.qc // id1 globalvars_t
+defs_entvars.qc // id1 entvars_t
+defs_builtins.qc // id1 / FTE builtin functions (& overrides)
+defs_misc.qc // additional
+defs_classtype.qc // global class list
//----------------------------------------------------------------------
// utility & helper functions
//----------------------------------------------------------------------
-math.qc // Code by Joshua Skelton
+math.qc // Code by Joshua Skelton + misc
utility.qc
-newflags.qc // new spawnflags for all entities
-cshift.qc // background color shift controller
-subs.qc // modified targets, triggers and killtargets
-keylock.qc // common code for entities unlockable with keys
-custom_snd.qc // mapper-settable sound FX for monsters - iw
-custom_mdls.qc // mapper-settable models for monsters - iw
-
-//----------------------------------------------------------------------
-// world
-//----------------------------------------------------------------------
-world.qc
+newflags.qc // new spawnflags for all entities
+cshift.qc // background color shift controller
+subs.qc // modified targets, triggers and killtargets
+keylock.qc // common code for entities unlockable with keys
+custom_snd.qc // mapper-settable sound FX for monsters - iw
+custom_mdls.qc // mapper-settable models for monsters - iw
+gore.qc // spawnblood etc; TODO CEV need to reformat
//----------------------------------------------------------------------
// base classes
//----------------------------------------------------------------------
-base_entities.qc // topmost entity classes
-base_func.qc // base func_ classes
-base_item.qc // ammo, armor, health, weapons, etc.
-base_monster.qc // base monster classes
-base_projectile.qc // projectiles
-base_trigger.qc // methods & fields for trigger entities
+base_entities.qc // topmost entity classes (+ damage functions)
+base_func.qc // base func_ classes
+base_item.qc // ammo, armor, health, weapons, etc.
+base_monster.qc // base monster classes (+ monster AI)
+base_projectile.qc // projectiles
+base_trigger.qc // methods & fields for trigger entities
//----------------------------------------------------------------------
// info entities -- destinations, targets, etc.
//----------------------------------------------------------------------
-info/camera.qc // was in cutscene.qc
-info/intermission.qc //
-info/null.qc // info_null; was in lights.qc
-info/notnull.qc // info_notnull; was in lights.qc
-info/path_corner.qc // id1 path_corner
-info/rotate.qc // hipnotic info_rotate
-info/teleport_changedest.qc // Qmaster's info_teleport_changedest
-info/teleport_destination.qc // teleporter endpoints
+info/camera.qc // was in cutscene.qc
+info/intermission.qc // intermission point entity
+info/null.qc // info_null; was in lights.qc
+info/notnull.qc // info_notnull; was in lights.qc
+info/path_corner.qc // id1 path_corner
+info/rotate.qc // hipnotic info_rotate
+info/spawnpoints.qc // info_player_etc and other spawnpoints
+info/teleport_changedest.qc // Qmaster's info_teleport_changedest
+info/teleport_destination.qc // teleporter endpoints
//----------------------------------------------------------------------
// projectiles - these were all previously in weapons.qc
//----------------------------------------------------------------------
-projectiles/bullet.qc // id1 shotguns
-projectiles/grenade.qc // id1 grenades
-projectiles/laser.qc // id1 lasers (enforcer, hazards)
-projectiles/rocket.qc // id1 rockets
-projectiles/spike.qc // id1 nails
+projectiles/bullet.qc // id1 shotguns
+projectiles/flak.qc // pd3 flak
+projectiles/grenade.qc // id1 grenades
+projectiles/hknightspell.qc // id1 Death Knight magic attack
+projectiles/laser.qc // id1 lasers (enforcer, hazards)
+projectiles/lavaball.qc // pd3 lava ball missiles
+projectiles/multigrenade.qc // pd3 & Hipnotic/Rogue multi/mini grenades
+projectiles/rocket.qc // id1 rockets
+projectiles/spike.qc // id1 nails
+projectiles/voreball.qc // id1 vore homing missile
+projectiles/wizardspell.qc // id1 Scrag green magic missile attack
+projectiles/zombiechunk.qc // id1 zombie flesh chunk (traditionally thrown)
//----------------------------------------------------------------------
// item entities & weapon firing code
//----------------------------------------------------------------------
-items/ammo.qc // ammo; was in items.qc
-items/armor.qc // armor; was in items.qc
-items/keys.qc // key pickups; contains items.qc and keydata.qc
-items/health.qc // health; was in items.qc
-items/powerups.qc // envirosuit, pent, ring, quad; was in items.qc
-items/runes.qc // end-of-episode runes; was in items.qc
-items/weapons.qc // weapon pickups; was in items.qc
-items/backpacks.qc // backpack code; was in items.qc
+items/ammo.qc // ammo; was in items.qc
+items/armor.qc // armor; was in items.qc
+items/keys.qc // key pickups; contains items.qc and keydata.qc
+items/health.qc // health; was in items.qc
+items/powerups.qc // envirosuit, pent, ring, quad; was in items.qc
+items/runes.qc // end-of-episode runes; was in items.qc
+items/weapons.qc // weapon pickups; was in items.qc
+items/backpacks.qc // backpack code; was in items.qc
//----------------------------------------------------------------------
-// combat & monster AI -- TODO CEV need to reformat
+// client & player code
//----------------------------------------------------------------------
-// fight.qc
-// ai.qc
-combat.qc
-weapons.qc // TODO CEV need to reformat
+cutscene.qc // Drake version -- dumptruck_ds
+obituary.qc // ClientObituary
+pmove.qc // QC player movement code -- CEV
//----------------------------------------------------------------------
-// client & player code
+// monster entities
//----------------------------------------------------------------------
-cutscene.qc // Drake version -- dumptruck_ds
-client/connect.qc // ClientConnect, ClientDisconnect
-client/impulse.qc // impulse cmd handling; was in weapons.qc -- CEV
-client/intermission.qc // intermission & exit screen text
-client/levelparms.qc // Level Changing; NextMap
-client/maprules.qc // Deathmatch NextLevel and CheckRules
-client/obituary.qc // ClientObituary
-client/playerspawn.qc // PutClientInServer, info_player ents, etc.
-player/player.qc // player animation frames, pain & death, etc.
-player/playerthink.qc // TODO CEV was in client.qc
-player/pmove.qc // QC player movement code -- CEV
+monsters/playerclient.qc // player and client handling
+monsters/boss.qc // id1 Chthon
+monsters/boss2.qc // pd3 killable Chthon
+monsters/dog.qc // id1 Doggo
+monsters/demon.qc // id1 Fiend
+monsters/knight.qc // id1 Knight
+monsters/ogre.qc // id1 Ogre
+monsters/shambler.qc // id1 Shambler
+monsters/soldier.qc // id1 Grunt
+monsters/wizard.qc // id1 Scragg / Wizard
+monsters/zombie.qc // modified Ace_Dave's zombies from Rubicon2
+monsters/enforcer.qc // id1 Enforcer (registered)
+monsters/fish.qc // id1 Fish (registered)
+monsters/hknight.qc // id1 Death Knight / Hell Knight (registered)
+monsters/oldone.qc // id1 Shub (registered)
+monsters/oldone2.qc // pd3 killable Shub
+monsters/shalrath.qc // id1 Vore (registered)
//----------------------------------------------------------------------
// func entities
//----------------------------------------------------------------------
-func/shadow.qc //
-func/wall.qc // was misc.qc -- CEV
-func/bob.qc // RennyC's stand alone version based on AD
-func/bossgate.qc // was misc.qc -- CEV
-func/breakable.qc // selections from Rubicon2 QC; was rubicon2.qc -- CEV
+func/shadow.qc //
+func/wall.qc // was misc.qc -- CEV
+func/bob.qc // RennyC's stand alone version based on AD
+func/bossgate.qc // was misc.qc -- CEV
+func/breakable.qc // selections from Rubicon2 QC
func/button.qc
-func/counter.qc // Hipnotic counter; was in hipcount.qc
-func/door.qc // was doors.qc -- CEV
-func/door_secret.qc // was doors.qc -- CEV
-func/elvtr_button.qc // Rogue elevator code (pmack)
-func/episodegate.qc // was misc.qc -- CEV
-func/explobox.qc // selections from Rubicon2 QC; was rubicon2.qc -- CEV
-func/fall.qc // Renny's original version
-func/fall2.qc // Renny's improved version.
-func/illusionary.qc // was misc.qc -- CEV
-func/laser.qc // selections from Rubicon2 QC; was rubicon2.qc -- CEV
-func/monster_spawner.qc // Using "bot" creation code for func_monster_spawner
-func/new_plat.qc // Rogue MP newplats.qc
-func/plat.qc // was plats.qc -- CEV
-func/particlefield.qc // Hipnotic particlefield and func_togglewall
-func/rotate.qc // from Hipnotic thanks RennyC; was rotate.qc
-func/togglevisiblewall.qc // was misc.qc -- CEV
-func/togglewall.qc // was hippart.qc -- CEV
-func/train.qc // was plats.qc -- CEV
+func/counter.qc // Hipnotic counter; was in hipcount.qc
+func/door.qc // was doors.qc -- CEV
+func/door_secret.qc // was doors.qc -- CEV
+func/elvtr_button.qc // Rogue elevator code (pmack)
+func/episodegate.qc // was misc.qc -- CEV
+func/explobox.qc // selections from Rubicon2 QC
+func/fall.qc // Renny's original version
+func/fall2.qc // Renny's improved version.
+func/illusionary.qc // was misc.qc -- CEV
+func/laser.qc // selections from Rubicon2 QC
+func/monster_spawner.qc // "bot" creation code for func_monster_spawner
+func/new_plat.qc // Rogue MP newplats.qc
+func/plat.qc // was plats.qc -- CEV
+func/particlefield.qc // Hipnotic particlefield and func_togglewall
+func/rotate.qc // from Hipnotic thanks RennyC; was rotate.qc
+func/togglevisiblewall.qc // was misc.qc -- CEV
+func/togglewall.qc // was hippart.qc -- CEV
+func/train.qc // was plats.qc -- CEV
//----------------------------------------------------------------------
// trigger & target entities
//----------------------------------------------------------------------
-triggers/multiple.qc // need to add first, subclassed below -- CEV
-triggers/camera.qc // was in cutscene.qc
-triggers/changelevel.qc //
-triggers/changemusic.qc //
+triggers/multiple.qc // need to add first, subclassed below -- CEV
+triggers/camera.qc // was in cutscene.qc
+triggers/changelevel.qc //
+triggers/changemusic.qc //
triggers/changetarget.qc
-triggers/counter.qc //
-triggers/cvarset.qc // was in cutscene.qc
-triggers/everything.qc // trigger_everything
-triggers/filter.qc //
-triggers/fog.qc // fog triggers
-triggers/heal.qc // trigger_heal (was in dtmisc.qc) -- CEV
-triggers/hurt.qc //
-triggers/ladder.qc // ladders (from rubicon2) -- CEV
-triggers/look.qc //
-triggers/monsterface.qc //
-triggers/monsterjump.qc //
+triggers/counter.qc //
+triggers/cvarset.qc // was in cutscene.qc
+triggers/everything.qc // trigger_everything
+triggers/filter.qc //
+triggers/fog.qc // fog triggers
+triggers/heal.qc // trigger_heal (was in dtmisc.qc) -- CEV
+triggers/hurt.qc //
+triggers/ladder.qc // ladders (from rubicon2) -- CEV
+triggers/look.qc //
+triggers/monsterface.qc //
+triggers/monsterjump.qc //
triggers/onlyregistered.qc
-triggers/push.qc // wind/push brushes, jumppads -- CEV
-triggers/remove.qc // was in hip_trig.qc; currently commented out -- CEV
-triggers/relay.qc //
-triggers/secret.qc //
-triggers/setcount.qc // target_setcount
-triggers/setgravity.qc // was in hip_trig.qc
-triggers/setskill.qc //
-triggers/setstate.qc // target_setstate
-triggers/shake.qc // triggerable shake from Zer cutscenes; was dtquake.qc
-triggers/take_weapon.qc //
-triggers/teleport.qc // was in triggers.qc -- CEV
-triggers/textstory.qc // textstory (was in misc.qc) -- CEV
-triggers/usekey.qc // was in hip_trig.qc -- CEV
-triggers/void.qc //
-
-//----------------------------------------------------------------------
-// monster entities -- TODO CEV need to reformat the monster code
-//----------------------------------------------------------------------
-monsters/boss.qc
-monsters/boss2.qc // killable Chthon
-monsters/dog.qc
-monsters/demon.qc
-monsters/knight.qc
-monsters/ogre.qc
-monsters/shambler.qc
-monsters/soldier.qc
-monsters/wizard.qc
-monsters/zombie.qc // modified ver. of Ace_Dave's zombies from Rubicon2
-monsters/enforcer.qc // registered
-monsters/fish.qc // registered
-monsters/hknight.qc // registered
-monsters/oldone.qc // registered
-monsters/oldone2.qc // killable Shub
-monsters/shalrath.qc // registered
-
-// monsters.qc // modified by dumptruck_ds from Preach's
- // spawning tutorial | fish count fixed
+triggers/push.qc // wind/push brushes, jumppads -- CEV
+triggers/remove.qc // was in hip_trig.qc; currently disabled -- CEV
+triggers/relay.qc //
+triggers/secret.qc //
+triggers/setcount.qc // target_setcount
+triggers/setgravity.qc // was in hip_trig.qc
+triggers/setskill.qc //
+triggers/setstate.qc // target_setstate
+triggers/shake.qc // triggerable shake from Zer cutscenes
+triggers/take_weapon.qc //
+triggers/teleport.qc // was in triggers.qc -- CEV
+triggers/textstory.qc // textstory (was in misc.qc) -- CEV
+triggers/usekey.qc // was in hip_trig.qc -- CEV
+triggers/void.qc //
//----------------------------------------------------------------------
// hazards
//----------------------------------------------------------------------
-hazards/ltrail.qc // from DOE lightnin.qc
-hazards/shooter.qc // was in misc.qc
+hazards/ltrail.qc // from DOE lightnin.qc
+hazards/shooter.qc // was in misc.qc
//----------------------------------------------------------------------
// miscellaneous entities
//----------------------------------------------------------------------
-misc/model.qc // Code by Joshua Skelton
-misc/air_bubbles.qc // was in misc.qc -- CEV
-misc/ambient_sound.qc // misc. ambient_ entities w/additions by dumptruck_ds
-misc/deadstuff.qc // misc gore from DeadStuff mod
-misc/explobox.qc // was in misc.qc -- CEV
-misc/fireball.qc // was in misc.qc -- CEV
-misc/infight.qc // was in misc.qc -- CEV
-misc/light_candle.qc // was in misc.qc -- CEV
-misc/lights.qc // c0burn's excellent switchable lights
-misc/modeltrain.qc // was in plats.qc -- CEV
-misc/noisemaker.qc // was in misc.qc -- CEV
-misc/particles.qc // selections from Rubicon2 QC; was rubicon2.qc -- CEV
-misc/particlespray.qc // selections from Rubicon2 QC; was rubicon2.qc -- CEV
-misc/particle_stream.qc // from Zerstrorer mod -- dumptruck_ds; was dtmisc.qc
-misc/play.qc // sound code from Hip & Rubicon Rumble + misc visuals
-misc/sparks.qc // selections from Rubicon2 QC; was rubicon2.qc -- CEV
-misc/target_autosave.qc // was in misc.qc -- CEV
-misc/teleporttrain.qc // was in plats.qc -- CEV
-misc/viewthing.qc // was in misc.qc -- CEV
+misc/model.qc // Code by Joshua Skelton
+misc/air_bubbles.qc // was in misc.qc -- CEV
+misc/ambient_sound.qc // misc ambient_ entities w/add. by dumptruck_ds
+misc/deadstuff.qc // misc gore from DeadStuff mod
+misc/explobox.qc // was in misc.qc -- CEV
+misc/fireball.qc // was in misc.qc -- CEV
+misc/infight.qc // was in misc.qc -- CEV
+misc/light_candle.qc // was in misc.qc -- CEV
+misc/lights.qc // c0burn's excellent switchable lights
+misc/modeltrain.qc // was in plats.qc -- CEV
+misc/noisemaker.qc // was in misc.qc -- CEV
+misc/particles.qc // selections from Rubicon2 QC; was rubicon2.qc
+misc/particlespray.qc // selections from Rubicon2 QC; was rubicon2.qc
+misc/particle_stream.qc // from Zerstrorer mod -- dumptruck_ds
+misc/play.qc // sound code from Hip & Rubicon Rumble + misc
+misc/sparks.qc // selections from Rubicon2 QC; was rubicon2.qc
+misc/target_autosave.qc // was in misc.qc -- CEV
+misc/teleporttrain.qc // was in plats.qc -- CEV
+misc/viewthing.qc // was in misc.qc -- CEV
+
+//----------------------------------------------------------------------
+// world
+//----------------------------------------------------------------------
+entrypoints.qc // server-side entrypoints
+world.qc // worldspawn
//----------------------------------------------------------------------
// compatibility spawn functions & misc
//----------------------------------------------------------------------
-compat_quake3.qc // entrypoints & support for Quake 3 entities
+compat_quake3.qc // entrypoints & support for Quake 3 entities
#endlist
Return to the top of this page or return to the overview of this repo.
Diff qc/projectiles/bullet.qc
diff --git a/qc/projectiles/bullet.qc b/qc/projectiles/bullet.qc
index a41f7b0..33e9ca2 100644
--- a/qc/projectiles/bullet.qc
+++ b/qc/projectiles/bullet.qc
@@ -1,8 +1,10 @@
-//======================================================================
-// Shotguns
-//======================================================================
+//==============================================================================
+// Bullets - shotguns & enemy soldiers
+//==============================================================================
+//======================================================================
// globals
+//======================================================================
entity multi_ent;
float multi_damage;
@@ -48,7 +50,7 @@ void() ApplyMultiDamage =
{
if (!multi_ent)
return;
- T_Damage (multi_ent, self, self, multi_damage);
+ base_entity::t_damage2 (multi_ent, self, self, multi_damage);
};
void(entity hit, float damage) AddMultiDamage =
@@ -68,7 +70,6 @@ void(entity hit, float damage) AddMultiDamage =
}
};
-
//----------------------------------------------------------------------
// FireBullets
// Used by shotgun, super shotgun, and enemy soldier firing. Go to the
@@ -99,44 +100,3 @@ void(float shotcount, vector dir, vector spread) FireBullets =
ApplyMultiDamage ();
};
-
-//----------------------------------------------------------------------
-// W_FireShotgun
-//----------------------------------------------------------------------
-void() W_FireShotgun =
-{
- local vector dir;
-
- sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -2;
-
- self.currentammo = self.ammo_shells = self.ammo_shells - 1;
- dir = aim (self, 100000);
- // TODO CEV
- FireBullets (6, dir, '0.04 0.04 0');
-};
-
-//----------------------------------------------------------------------
-// W_FireSuperShotgun
-//----------------------------------------------------------------------
-void() W_FireSuperShotgun =
-{
- local vector dir;
-
- if (self.currentammo == 1)
- {
- W_FireShotgun ();
- return;
- }
-
- sound (self, CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -4;
-
- self.currentammo = self.ammo_shells = self.ammo_shells - 2;
- dir = aim (self, 100000);
- FireBullets (14, dir, '0.14 0.08 0');
-};
-
-
Return to the top of this page or return to the overview of this repo.
Diff qc/projectiles/flak.qc
diff --git a/qc/projectiles/flak.qc b/qc/projectiles/flak.qc
new file mode 100644
index 0000000..fd39987
--- /dev/null
+++ b/qc/projectiles/flak.qc
@@ -0,0 +1,149 @@
+//==============================================================================
+// Flak
+// BDW 31/08/00 - evil, nasty red-hot nail cluster-bomb attack...
+// from Marcher -- dumptruck_ds
+//==============================================================================
+
+//======================================================================
+// constants
+//======================================================================
+const float FLAK_DIRECT_DAMAGE = 4; // default direct damage
+ // flak doesn't splash
+const float FLAK_SPEED = 800; // speed of BDW's OgreFireFlak
+
+const vector FLAK_MINS = '0 0 0'; // let's not change this -- CEV
+const vector FLAK_MAXS = '0 0 0'; //
+
+//======================================================================
+// fields
+//======================================================================
+
+// bdw - saves up flak hits to do a single damage next frame -
+// currently only used for flak ogre
+.float spikecount;
+
+//------------------------------------------------------------------------------
+class projectile_flak: base_projectile
+{
+ //--------------------------------------------------------------
+ // FlakDoDamage
+ //--------------------------------------------------------------
+ nonvirtual void() think_damage =
+ {
+ // get correct gib direction
+ this.origin = this.oldenemy.origin + this.oldorigin;
+ this.t_damage2 (this.oldenemy, this, this.owner,
+ this.oldenemy.spikecount);
+ this.oldenemy.spikecount = 0;
+ remove (this);
+ };
+
+ //--------------------------------------------------------------
+ // FlakTouch
+ //--------------------------------------------------------------
+ virtual void(entity toucher) do_touch =
+ {
+ if (toucher.solid == SOLID_TRIGGER)
+ return;
+
+ // hit something that bleeds
+ if (toucher.takedamage)
+ {
+ spawn_touchblood (this.direct_damage);
+
+ sound (this, CHAN_VOICE, "fish/bite.wav", 1, ATTN_NORM);
+
+ if (toucher.spikecount)
+ {
+ // not the first one
+ toucher.spikecount += this.direct_damage;
+ remove (this);
+ return;
+ }
+
+ // the first one...
+ toucher.spikecount = this.direct_damage;
+
+ // stick around for a little while...
+ this.velocity = '0 0 0';
+ this.solid = SOLID_NOT;
+ this.touch = sub_null;
+ this.model = string_null;
+ // displacement from enemy origin (its gonna
+ // move next frame)
+ this.oldorigin = this.origin - toucher.origin;
+ this.oldenemy = toucher;
+ this.think = this.think_damage;
+ this.nextthink = time + 0.05;
+ return;
+ }
+
+ WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
+ WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
+ WriteCoord (MSG_BROADCAST, this.origin_x);
+ WriteCoord (MSG_BROADCAST, this.origin_y);
+ WriteCoord (MSG_BROADCAST, this.origin_z);
+
+ // bit of a hack
+ if (this.spawnflags & MONSTER_FLAK_OGRE)
+ {
+ remove (this);
+ return;
+ }
+
+ // gets weaker with each bounce.
+ // also stops them getting stuck in world.
+ this.direct_damage = this.direct_damage - 5;
+ if (this.direct_damage <= 0)
+ {
+ remove (this);
+ return;
+ }
+
+ // reduce crazy ricochets
+ this.velocity = this.velocity * 0.5;
+ this.movetype = MOVETYPE_BOUNCE;
+ };
+
+ //--------------------------------------------------------------
+ void() projectile_flak =
+ {
+ this.classtype = CT_PROJECTILE_FLAK;
+ // flymissile is a bit too all-seeing for this gun...
+ this.movetype = MOVETYPE_FLY;
+ this.solid = SOLID_BBOX;
+ this.flags = FL_NOSELECT;
+ this.angles = vectoangles (this.velocity);
+
+ if (!this.proj_basespeed)
+ this.proj_basespeed = FLAK_SPEED;
+
+ if (!this.direct_damage)
+ this.direct_damage = FLAK_DIRECT_DAMAGE;
+
+ // dumptruck_ds
+ if (this.mdl_proj && this.mdl_proj != "")
+ setmodel (this, this.mdl_proj);
+ else
+ setmodel (this, "progs/spike.mdl");
+
+ // if (this.skin_proj)
+ // this.skin = this.skin_proj;
+ // else
+ this.skin = 0;
+ // dumptruck_ds - end
+
+ if (this.homing > 0)
+ {
+ setup_homing (proj_basespeed * proj_speed_mod);
+ }
+ else
+ {
+ this.nextthink = time + 6;
+ this.think = sub_remove;
+ }
+
+ setsize (this, FLAK_MINS, FLAK_MAXS);
+ setorigin (this, this.origin);
+ };
+};
Return to the top of this page or return to the overview of this repo.
Diff qc/projectiles/grenade.qc
diff --git a/qc/projectiles/grenade.qc b/qc/projectiles/grenade.qc
index 36ba547..94f573e 100644
--- a/qc/projectiles/grenade.qc
+++ b/qc/projectiles/grenade.qc
@@ -2,23 +2,42 @@
// Grenades
//==============================================================================
+//======================================================================
+// constants
+//======================================================================
+const float GRENADE_DIRECT_DAMAGE = 100;// direct damage; 100 is id1
+const float GRENADE_SPLASH_DAMAGE = 120;// splash damage; 120 is id1
+const float GRENADE_SPEED = 600; // id1 grenade speed is 600
+const float GRENADE_HEALTH = 20; // explodes when dead
+
+// found using FTE's sv_gameplayfix_setmodelrealbox
+// const vector GRENADE_MINS = '-8.57384 -3.71142 -3.94197';
+// const vector GRENADE_MAXS = '10.2459 3.68095 4.05187';
+const vector GRENADE_MINS = '-8 -8 -8'; // a little more generous -- CEV
+const vector GRENADE_MAXS = '8 8 8';
+
//------------------------------------------------------------------------------
-class projectile_grenade: base_projectile
+class projectile_grenade: base_projectile_qcphys
{
float count;
//--------------------------------------------------------------
+ virtual void() do_destroy =
+ {
+ dprint (sprintf("projectile_grenade::do_destroy: exploding\n"));
+ this.do_think ();
+ };
+
+ //--------------------------------------------------------------
virtual void() do_think =
{
- T_RadiusDamage (this, this.owner, 120, other);
+ if (this.takedamage)
+ this.takedamage = DAMAGE_NO;
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, TE_EXPLOSION);
- WriteCoord (MSG_BROADCAST, this.origin_x);
- WriteCoord (MSG_BROADCAST, this.origin_y);
- WriteCoord (MSG_BROADCAST, this.origin_z);
+ t_radiusdamage2 (this, this.owner, this.splash_damage, other);
// BecomeExplosion
+ base_explosion::write_explosion (this.origin);
spawn (base_explosion, origin: this.origin);
remove (this);
};
@@ -53,27 +72,22 @@ class projectile_grenade: base_projectile
// grenades deal to any of the original monsters under any
// circumstances. -- iw
//--------------------------------------------------------------
- virtual void(entity toucher) do_touch =
+ virtual void(entity toucher) do_touch_explosive =
{
- local float damg;
-
- if (other == this.owner)
- // don't explode on owner
- return;
-
- if (other.takedamage == DAMAGE_AIM)
+ if (toucher.takedamage == DAMAGE_AIM)
{
// see the explanation above -- iw
- if (other.size_x > VEC_HULL2_SIZE_x ||
- other.size_y > VEC_HULL2_SIZE_y ||
- other.size_z > VEC_HULL2_SIZE_z)
+ if (toucher.size_x > VEC_HULL2_SIZE_x ||
+ toucher.size_y > VEC_HULL2_SIZE_y ||
+ toucher.size_z > VEC_HULL2_SIZE_z)
{
// note that the logic for monster_shambler's
// partial immunity to explosions is not
// required because this is only for entities
// which are larger than monster_shambler -- iw
- damg = 100 + random() * 20;
- T_Damage (other, this, this.owner, damg);
+ // dmg = this.direct_dmg + random() * 20;
+ t_damage2 (toucher, this, this.owner,
+ this.direct_damage);
this.do_think ();
return;
}
@@ -81,13 +95,15 @@ class projectile_grenade: base_projectile
this.do_think ();
return;
}
+
if (this.count < time)
{
// bounce sound
sound (this, CHAN_WEAPON, "weapons/bounce.wav",
1, ATTN_NORM);
}
- this.count = time + .02;
+
+ this.count = time + 0.02;
if (this.velocity == '0 0 0')
this.avelocity = '0 0 0';
};
@@ -95,82 +111,42 @@ class projectile_grenade: base_projectile
//--------------------------------------------------------------
void() projectile_grenade =
{
+ this.classtype = CT_PROJECTILE_GRENADE;
this.classname = "grenade";
- this.classtype = CT_TEMP_GRENADE;
this.movetype = MOVETYPE_BOUNCE;
this.solid = SOLID_BBOX;
- this.avelocity = '300 300 300';
+ this.explosive = TRUE;
+ this.health = GRENADE_HEALTH;
+ this.takedamage = DAMAGE_YES;
this.angles = vectoangles (this.velocity);
- // set missile duration
- this.nextthink = time + 2.5;
- setmodel (this, "progs/grenade.mdl");
- setsize (this, '0 0 0', '0 0 0');
- setorigin (this, this.origin);
- };
-};
+ if (!this.avelocity)
+ this.avelocity = '300 300 300';
-//----------------------------------------------------------------------
-// GrenadeExplode2
-//
-// This is the same as the original GrenadeExplode function except that
-// it will ignore the entity specified by the "ignore" parameter when
-// dealing damage. -- iw
-//----------------------------------------------------------------------
-void(entity ignore) GrenadeExplode2 =
-{
- T_RadiusDamage (self, self.owner, 120, ignore);
-
- 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 (!this.proj_basespeed)
+ this.proj_basespeed = GRENADE_SPEED;
- spawn (base_explosion, origin: self.origin);
- remove (self);
-};
+ // default damage for player grenades -- CEV
+ if (!this.direct_damage)
+ this.direct_damage = GRENADE_DIRECT_DAMAGE;
-//----------------------------------------------------------------------
-// GrenadeExplode -- Refactored. -- iw
-//----------------------------------------------------------------------
-void() GrenadeExplode =
-{
- GrenadeExplode2 (world);
-};
-
-//----------------------------------------------------------------------
-// W_FireGrenade -- TODO CEV move into base_monster (when it's written)
-//----------------------------------------------------------------------
-void() W_FireGrenade =
-{
- local entity missile;
- local vector missile_velocity = '0 0 0';
+ if (!this.splash_damage)
+ this.splash_damage = GRENADE_SPLASH_DAMAGE;
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
+ if (this.mdl_proj && this.mdl_proj != "")
+ setmodel (this, this.mdl_proj);
+ else
+ setmodel (this, "progs/grenade.mdl");
- sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
+ if (this.skin_proj)
+ this.skin = this.skin_proj;
+ else
+ this.skin = 0;
- self.punchangle_x = -2;
-
- // set missile speed
- makevectors (self.v_angle);
+ setsize (this, GRENADE_MINS, GRENADE_MAXS);
+ setorigin (this, this.origin);
- if (self.v_angle_x)
- {
- missile_velocity = v_forward * 600 +
- v_up * 200 + crandom() * v_right * 10 +
- crandom() * v_up * 10;
- }
- else
- {
- missile_velocity = aim (self, 10000);
- missile_velocity = missile_velocity * 600;
- missile_velocity_z = 200;
- }
-
- missile = spawn (projectile_grenade,
- owner: self,
- origin: self.origin,
- velocity: missile_velocity);
+ // schedule next think (explosion time)
+ this.nextthink = time + 2.5;
+ };
};
Return to the top of this page or return to the overview of this repo.
Diff qc/projectiles/hknightspell.qc
diff --git a/qc/projectiles/hknightspell.qc b/qc/projectiles/hknightspell.qc
new file mode 100644
index 0000000..a74ed6d
--- /dev/null
+++ b/qc/projectiles/hknightspell.qc
@@ -0,0 +1,74 @@
+//==============================================================================
+// Death Knight Magic Missile
+//==============================================================================
+
+//======================================================================
+// constants
+//======================================================================
+const float HKNSPELL_DIRECT_DAMAGE = 9; // direct damage; 9 is id1
+const float HKNSPELL_SPLASH_DAMAGE = 50;// splash damage; 50 is pd3
+const float HKNSPELL_EXPLOD_DAMAGE = 20;// explosive direct damage; 20 is pd3
+const float HKNSPELL_SPEED = 300; // id1 Death Knight missile is 300ups
+
+const vector HKNSPELL_MINS = '0 0 0'; // let's not change this -- CEV
+const vector HKNSPELL_MAXS = '0 0 0'; //
+
+//------------------------------------------------------------------------------
+class projectile_hknightspell: base_projectile
+{
+ float spell_offset;
+
+ //--------------------------------------------------------------
+ void() projectile_hknightspell =
+ {
+ this.classtype = CT_PROJECTILE_HKNIGHT;
+ this.classname = "knightspike";
+ this.movetype = MOVETYPE_FLYMISSILE;
+ this.solid = SOLID_BBOX;
+ this.explosive = parse_projexpl (projexpl, spell_offset);
+ this.angles = vectoangles (this.velocity);
+
+ if (!this.proj_basespeed)
+ this.proj_basespeed = HKNSPELL_SPEED;
+
+ if (!this.direct_damage)
+ if (this.explosive)
+ this.direct_damage = HKNSPELL_EXPLOD_DAMAGE;
+ else
+ this.direct_damage = HKNSPELL_DIRECT_DAMAGE;
+
+ if (!this.splash_damage)
+ if (this.explosive)
+ this.splash_damage = HKNSPELL_SPLASH_DAMAGE;
+ else
+ this.splash_damage = 0;
+
+ // dumptruck_ds custom_mdls
+ if (this.mdl_proj != "")
+ setmodel (this, this.mdl_proj);
+ else
+ if (explosive)
+ setmodel (this, "progs/k_spike2.mdl");
+ else
+ setmodel (this, "progs/k_spike.mdl");
+
+ // dumptruck_ds
+ if (this.skin_proj)
+ this.skin = this.skin_proj;
+ else
+ this.skin = 0;
+
+ if (this.homing > 0)
+ {
+ setup_homing (proj_basespeed * proj_speed_mod);
+ }
+ else
+ {
+ this.think = sub_remove;
+ this.nextthink = time + 6;
+ }
+
+ setsize (this, HKNSPELL_MINS, HKNSPELL_MAXS);
+ setorigin (this, this.origin);
+ };
+};
Return to the top of this page or return to the overview of this repo.
Diff qc/projectiles/laser.qc
diff --git a/qc/projectiles/laser.qc b/qc/projectiles/laser.qc
index e69de29..d37e28b 100644
--- a/qc/projectiles/laser.qc
+++ b/qc/projectiles/laser.qc
@@ -0,0 +1,83 @@
+//==============================================================================
+// Laser Projectile (Enforcers, etc)
+//==============================================================================
+
+//======================================================================
+// constants
+//======================================================================
+const float LASER_DIRECT_DAMAGE = 15; // direct damage; 15 is id1
+ // lasers don't splash
+const float LASER_SPEED = 600; // id1 laser speed is 600
+
+const vector LASER_MINS = '0 0 0'; // let's not change this -- CEV
+const vector LASER_MAXS = '0 0 0'; //
+
+//------------------------------------------------------------------------------
+class projectile_laser: base_projectile
+{
+ //--------------------------------------------------------------
+ virtual void(entity toucher) do_touch =
+ {
+ // dumptruck_ds
+ sound_hit (this, CHAN_WEAPON, "enforcer/enfstop.wav",
+ 1, ATTN_STATIC);
+ local vector org = this.origin - 8 * normalize (this.velocity);
+
+ if (toucher.health)
+ {
+ SpawnBlood (org, this.velocity * 0.2, direct_damage);
+ t_damage2 (toucher, this, this.owner, direct_damage);
+ }
+ else
+ {
+ 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);
+ }
+
+ remove (this);
+ };
+
+ //--------------------------------------------------------------
+ void() projectile_laser =
+ {
+ this.classtype = CT_PROJECTILE_LASERBEAM;
+ this.movetype = MOVETYPE_FLY;
+ this.solid = SOLID_BBOX;
+ this.effects = EF_DIMLIGHT;
+ this.angles = vectoangles (this.velocity);
+
+ if (!this.proj_basespeed)
+ this.proj_basespeed = LASER_SPEED;
+
+ if (!this.direct_damage)
+ this.direct_damage = LASER_DIRECT_DAMAGE;
+
+ // dumptruck_ds
+ if (this.mdl_proj != "")
+ setmodel (this, this.mdl_proj);
+ else
+ setmodel (this, "progs/laser.mdl");
+
+ // dumptruck_ds
+ if (this.skin_proj)
+ this.skin = this.skin_proj;
+ else
+ this.skin = 0;
+
+ if (this.homing > 0)
+ {
+ setup_homing (proj_basespeed * proj_speed_mod);
+ }
+ else
+ {
+ this.nextthink = time + 5;
+ this.think = sub_remove;
+ }
+
+ setsize (this, LASER_MINS, LASER_MAXS);
+ setorigin (this, this.origin);
+ };
+};
Return to the top of this page or return to the overview of this repo.
Diff qc/projectiles/lavaball.qc
diff --git a/qc/projectiles/lavaball.qc b/qc/projectiles/lavaball.qc
new file mode 100644
index 0000000..0cc2962
--- /dev/null
+++ b/qc/projectiles/lavaball.qc
@@ -0,0 +1,83 @@
+//==============================================================================
+// Chthon Lavaball
+//==============================================================================
+
+//======================================================================
+// constants
+//======================================================================
+const float LAVABALL_DIRECT_DAMAGE = 100;// direct damage; 100 is id1
+const float LAVABALL_SPLASH_DAMAGE = 120;// splash damage; 120 is id1
+const float LAVABALL_SPEED = 300; // id1 Chthon fires at 300ups
+const float LAVABALL_HEALTH = 100; // much more difficult to destroy
+
+// found using FTE's sv_gameplayfix_setmodelrealbox
+// const vector LAVABALL_MINS = '-4.06976 -7.56844 -3.0414';
+// const vector LAVABALL_MAXS = '9.56484 7.31226 13.5418';
+const vector LAVABALL_MINS = '-7 -7 -8';// slightly more generous mins & maxs
+const vector LAVABALL_MAXS = '7 7 8';
+
+//------------------------------------------------------------------------------
+class projectile_lavaball: base_projectile_qcphys
+{
+ //--------------------------------------------------------------
+ virtual void() do_destroy =
+ {
+ // dprint ("projectile_lavaball::do_destroy: exploding...\n");
+ this.do_touch_explosive (world);
+ };
+
+ //--------------------------------------------------------------
+ // Touch is handled by base_projectile -- CEV
+ //--------------------------------------------------------------
+
+ //--------------------------------------------------------------
+ void() projectile_lavaball =
+ {
+ this.classtype = CT_PROJECTILE_LAVABALL;
+ this.classname = "lavaball";
+ this.movetype = MOVETYPE_FLYMISSILE;
+ this.solid = SOLID_BBOX;
+ this.explosive = TRUE;
+ this.health = LAVABALL_HEALTH;
+ this.takedamage = DAMAGE_YES;
+ this.angles = vectoangles (this.velocity);
+
+ // trap_shooter sets avelocity to '0 0 400' -- CEV
+ if (!this.avelocity)
+ this.avelocity = '200 100 300';
+
+ if (!this.proj_basespeed)
+ this.proj_basespeed = LAVABALL_SPEED;
+
+ if (!this.direct_damage)
+ this.direct_damage = LAVABALL_DIRECT_DAMAGE;
+
+ if (!this.splash_damage)
+ this.splash_damage = LAVABALL_SPLASH_DAMAGE;
+
+ // dumptruck_ds custom_mdls
+ if (this.mdl_proj != "")
+ setmodel (this, this.mdl_proj);
+ else
+ setmodel (this, "progs/lavaball.mdl");
+
+ // dumptruck_ds
+ if (this.skin_proj)
+ this.skin = this.skin_proj;
+ else
+ this.skin = 0;
+
+ if (this.homing > 0)
+ {
+ setup_homing (proj_basespeed * proj_speed_mod);
+ }
+ else
+ {
+ this.think = sub_remove;
+ this.nextthink = time + 6;
+ }
+
+ setsize (this, LAVABALL_MINS, LAVABALL_MAXS);
+ setorigin (this, this.origin);
+ };
+};
Return to the top of this page or return to the overview of this repo.
Diff qc/projectiles/multigrenade.qc
diff --git a/qc/projectiles/multigrenade.qc b/qc/projectiles/multigrenade.qc
new file mode 100644
index 0000000..a518443
--- /dev/null
+++ b/qc/projectiles/multigrenade.qc
@@ -0,0 +1,207 @@
+//==============================================================================
+// Multi Grenade Code from doe progs MULT_WPN.QC -- dumptruck_ds
+//==============================================================================
+
+//======================================================================
+// constants
+//======================================================================
+const float MININADE_SPLASH_DAMAGE = 35;// PD3 is 90 for player, 60 other
+const float MULTINADE_SPLASH_DAMAGE = 35;// 35 is the tribolt from QC
+const float MULTINADE_HEALTH = 5; //
+
+const vector MININADE_MINS = '0 0 0'; // zero size for mininades
+const vector MININADE_MAXS = '0 0 0';
+const vector MULTINADE_MINS = '-8 -8 -8';// a generous grenade size -- CEV
+const vector MULTINADE_MAXS = '8 8 8';
+
+//------------------------------------------------------------------------------
+class base_doegrenade: base_projectile
+{
+ //--------------------------------------------------------------
+ // MiniGrenadeExplode
+ //--------------------------------------------------------------
+ nonvirtual void() minigrenade_explode =
+ {
+ if (this.takedamage)
+ this.takedamage = DAMAGE_NO;
+
+ // removed distinction between player and monster-fired
+ // minigrenades in favor of a fixed common damage -- CEV
+ t_radiusdamage2 (this, this.owner, splash_damage, world);
+
+ // BecomeExplosion
+ base_explosion::write_explosion2 (this.origin);
+ // TODO CEV what are the following two writes doing?
+ WriteByte (MSG_BROADCAST, 230);
+ WriteByte (MSG_BROADCAST, 5);
+ spawn (base_explosion, origin: this.origin);
+ remove (this);
+ };
+};
+
+//------------------------------------------------------------------------------
+class projectile_minigrenade: base_doegrenade
+{
+ //--------------------------------------------------------------
+ virtual void() do_think =
+ {
+ minigrenade_explode ();
+ };
+
+ //--------------------------------------------------------------
+ // MultiGrenadeTouch (modified)
+ //--------------------------------------------------------------
+ virtual void(entity toucher) do_touch_explosive =
+ {
+ if (toucher.takedamage == DAMAGE_AIM)
+ {
+ minigrenade_explode ();
+ return;
+ }
+
+ // bounce sound
+ sound (this, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
+ if (this.velocity == '0 0 0')
+ this.avelocity = '0 0 0';
+ };
+
+ //--------------------------------------------------------------
+ void() projectile_minigrenade =
+ {
+ this.classtype = CT_PROJECTILE_MINIGRENADE;
+ this.classname = "MiniGrenade";
+ this.movetype = MOVETYPE_BOUNCE;
+ this.solid = SOLID_BBOX;
+ this.explosive = TRUE;
+ this.angles = vectoangles (this.velocity);
+
+ if (!this.avelocity)
+ this.avelocity = '300 300 300';
+
+ // reuse grenade speed -- CEV
+ // if (!this.proj_basespeed)
+ // this.proj_basespeed = GRENADE_SPEED;
+
+ if (!this.splash_damage)
+ this.splash_damage = MININADE_SPLASH_DAMAGE;
+
+ setmodel (this, "progs/mervup.mdl");
+ this.skin = 0;
+
+ setsize (this, MININADE_MINS, MININADE_MAXS);
+ setorigin (this, this.origin);
+
+ // set missile duration
+ this.nextthink = time + 1 + (crandom() * 0.5);
+ };
+};
+
+//------------------------------------------------------------------------------
+class projectile_multigrenade: base_doegrenade
+{
+ //--------------------------------------------------------------
+ virtual void() do_destroy =
+ {
+ dprint ("projectile_multigrenade::do_destroy: exploding...\n");
+ this.minigrenade_explode ();
+ };
+
+ //--------------------------------------------------------------
+ // MiniGrenadeLaunch
+ //--------------------------------------------------------------
+ nonvirtual void(float offset_angle) fire_minigrenade =
+ {
+ local entity missile;
+ local float temp_rand;
+ local vector missile_angle, missile_velocity;
+
+ // figure out missile speed
+ missile_angle = this.v_angle;
+ missile_angle_y = missile_angle_y + offset_angle;
+ makevectors (missile_angle);
+
+ // TODO CEV some suspicious fixed values here
+ missile_velocity = v_forward * 100 + v_up * 400;
+ temp_rand = (crandom() * 60) - 30;
+ missile_velocity += temp_rand * v_forward;
+ temp_rand = (crandom() * 40) - 20;
+ missile_velocity += temp_rand * v_right;
+ temp_rand = (crandom() * 60) - 30;
+ missile_velocity += temp_rand * v_up;
+
+ missile = spawn (projectile_minigrenade,
+ owner: this.owner,
+ origin: this.origin,
+ velocity: missile_velocity);
+ };
+
+ //--------------------------------------------------------------
+ // MultiGrenadeExplode
+ //--------------------------------------------------------------
+ virtual void() do_think =
+ {
+ fire_minigrenade (0);
+ fire_minigrenade (72);
+ fire_minigrenade (144);
+ fire_minigrenade (216);
+ fire_minigrenade (288);
+
+ remove (this);
+ };
+
+ //--------------------------------------------------------------
+ // MultiGrenadeTouch (modified)
+ //--------------------------------------------------------------
+ virtual void(entity toucher) do_touch_explosive =
+ {
+ if (toucher.takedamage == DAMAGE_AIM)
+ {
+ // this previously called GrenadeExplode if fired
+ // by the player or MiniGrenadeExplode if fired
+ // by anything else. I've changed that. -- CEV
+ minigrenade_explode ();
+ return;
+ }
+
+ // bounce sound
+ sound (this, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
+ if (this.velocity == '0 0 0')
+ this.avelocity = '0 0 0';
+ };
+
+ //--------------------------------------------------------------
+ void() projectile_multigrenade =
+ {
+ this.classtype = CT_PROJECTILE_MULTIGRENADE;
+ this.classname = "MultiGrenade";
+ this.movetype = MOVETYPE_BOUNCE;
+ this.solid = SOLID_BBOX;
+ this.explosive = TRUE;
+ this.health = MULTINADE_HEALTH;
+ this.takedamage = DAMAGE_YES;
+ this.angles = vectoangles (this.velocity);
+
+ if (!this.avelocity)
+ this.avelocity = '300 300 300';
+
+ // reuse grenade speed -- CEV
+ if (!this.proj_basespeed)
+ this.proj_basespeed = GRENADE_SPEED;
+
+ if (!this.splash_damage)
+ this.splash_damage = MULTINADE_SPLASH_DAMAGE;
+
+ setmodel (this, "progs/mervup.mdl");
+ this.skin = 0;
+
+ setsize (this, MULTINADE_MINS, MULTINADE_MAXS);
+ setorigin (this, this.origin);
+
+ // set missile duration
+ this.nextthink = time + 1;
+ };
+};
+
+//----------------------------------------------------------------------
+// end doe qc -- dumptruck_ds
+//----------------------------------------------------------------------
Return to the top of this page or return to the overview of this repo.
Diff qc/projectiles/rocket.qc
diff --git a/qc/projectiles/rocket.qc b/qc/projectiles/rocket.qc
index e934fcd..596ffc8 100644
--- a/qc/projectiles/rocket.qc
+++ b/qc/projectiles/rocket.qc
@@ -2,228 +2,79 @@
// Rockets
//======================================================================
-void() T_MissileTouch =
+//======================================================================
+// constants
+//======================================================================
+const float ROCKET_DIRECT_DAMAGE = 100; // direct damage; 100 is id1
+const float ROCKET_SPLASH_DAMAGE = 120; // splash damage; 120 is id1
+const float ROCKET_SPEED = 1000; // id1 1000ups
+const float ROCKET_HEALTH = 20; // explodes when dead
+
+// found using FTE's sv_gameplayfix_setmodelrealbox
+// const vector ROCKET_MINS = '-9.75537 -3.24751 -3.1833';
+// const vector ROCKET_MAXS = '8.52919 3.144 3.13116';
+const vector ROCKET_MINS = '-9 -4 -4'; // slightly more regular bounds
+const vector ROCKET_MAXS = '9 4 4';
+
+//------------------------------------------------------------------------------
+class projectile_rocket: base_projectile_qcphys
{
- local float damg;
-
- if (other == self.owner)
- // don't explode on owner
- return;
-
- if (pointcontents(self.origin) == CONTENT_SKY)
+ //--------------------------------------------------------------
+ virtual void() do_destroy =
{
- remove (self);
- return;
- }
-
- damg = 100 + random() * 20;
-
- if (other.health)
- {
- if (other.classname == "monster_shambler")
- // mostly immune
- damg = damg * 0.5;
- T_Damage (other, self, self.owner, damg);
- }
-
- // don't do radius damage to the other, because all the damage
- // was done in the impact
- T_RadiusDamage (self, self.owner, 120, other);
-
- // sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
- self.origin = self.origin - 8*normalize(self.velocity);
-
- 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);
-
- // BecomeExplosion
- spawn (base_explosion, origin: self.origin);
- remove (self);
-};
-
-// dumptruck_ds start -- from inside qc tut http://www.insideqc.com/qctut/lesson-32.shtml
-
-void(float direct, float splash) T_MonsterMisTouch =
-{
- local float damg;
-
- if (other == self.owner)
- // don't explode on owner
- return;
-
- if (pointcontents(self.origin) == CONTENT_SKY)
- {
- remove (self);
- return;
- }
-
- // dumptruck_ds
- damg = direct + random() * 2;
-
- if (other.health)
- {
- if (other.classname == "monster_shambler")
- // mostly immune
- damg = damg * 0.5;
- T_Damage (other, self, self.owner, damg);
- }
-
- // don't do radius damage to the other, because all the damage
- // was done in the impact
- T_RadiusDamage (self, self.owner, splash, other); // dumptruck_ds
-
- // sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
- self.origin = self.origin - 8 * normalize(self.velocity);
-
- 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);
-
- // BecomeExplosion
- spawn (base_explosion, origin: self.origin);
- remove (self);
-};
-
-void() T_GruntMisTouch =
-{
- T_MonsterMisTouch (30, 40);
-};
-
- // less direct damage, more splash than grunt
- // TODO: add damage modifier
-void() T_HellKnightMisTouch =
-{
- T_MonsterMisTouch (20, 50);
-};
-
-// big damage. explody scrag should be beefy.
-// TODO: add damage modifier
-void() T_WizardMisTouch =
-{
- T_MonsterMisTouch (50, 50);
-};
-// dumptruck_ds end
-
-//----------------------------------------------------------------------
-// W_FireRocket
-//----------------------------------------------------------------------
-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 = missile.velocity * 1000;
- missile.angles = vectoangles (missile.velocity);
-
- 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 * 8 + '0 0 16');
-};
-
-//----------------------------------------------------------------------
-// W_GruntRocket
-// dumptruck_ds start -- from inside qc tut
-// http://www.insideqc.com/qctut/lesson-32.shtml
-//----------------------------------------------------------------------
-void() W_GruntRocket =
-{
- local entity missile;
-
- /*
- // dumptruck_ds
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
- */
-
- sound_attack (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
+ dprint ("projectile_rocket::do_destroy: exploding...\n");
+ this.do_touch_explosive (world);
+ };
- self.punchangle_x = -2;
+ //--------------------------------------------------------------
+ // Touch is handled by base_projectile -- CEV
+ //--------------------------------------------------------------
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_FLYMISSILE;
- missile.solid = SOLID_BBOX;
- missile.classname = "missile";
-
- // set missile speed -- dumptruck_ds below
-
- missile.velocity = normalize (self.enemy.origin - self.origin);
- SetSpeed (missile, missile.velocity, 900 * self.proj_speed_mod);
- missile.angles = vectoangles (missile.velocity);
- missile.touch = T_GruntMisTouch;
-
- // makevectors (self.v_angle);
- // missile.velocity = aim(self, 1000);
- // missile.velocity = missile.velocity * 1000;
- // missile.angles = vectoangles(missile.velocity);
-
- // missile.touch = T_MissileTouch;
-
- // set missile duration
- if (self.homing > 0)
- {
- SetupHoming (missile, 900 * self.proj_speed_mod);
- }
- else
- {
- missile.nextthink = time + 5;
- missile.think = sub_remove;
- }
-
- if (self.mdl_proj != "")
+ //--------------------------------------------------------------
+ void() projectile_rocket =
{
- // dumptruck_ds
- setmodel (missile, self.mdl_proj);
- }
- else
- {
- setmodel (missile, "progs/missile.mdl");
- }
+ this.classtype = CT_PROJECTILE_ROCKET;
+ this.classname = "missile";
+ this.movetype = MOVETYPE_FLYMISSILE;
+ this.solid = SOLID_BBOX;
+ this.explosive = TRUE;
+ this.health = ROCKET_HEALTH;
+ this.takedamage = DAMAGE_YES;
+ this.angles = vectoangles (this.velocity);
+
+ if (!this.proj_basespeed)
+ this.proj_basespeed = ROCKET_SPEED;
+
+ if (!this.direct_damage)
+ this.direct_damage = ROCKET_DIRECT_DAMAGE;
+
+ if (!this.splash_damage)
+ this.splash_damage = ROCKET_SPLASH_DAMAGE;
+
+ // dumptruck_ds custom_mdls
+ if (this.mdl_proj != "")
+ setmodel (this, this.mdl_proj);
+ else
+ setmodel (this, "progs/missile.mdl");
- if (!missile.skin_proj)
- {
// dumptruck_ds
- missile.skin = self.skin_proj;
- }
- else
- {
- missile.skin = 0;
- }
- // dumptruck_ds - end
-
- // setmodel (missile, "progs/missile.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- // thanks Voidforce -- dumptruck_ds
- makevectors (self.angles);
- setorigin (missile, self.origin + v_forward * 30 +
- v_right * 5 + '0 0 12');
- // setorigin (missile, self.origin + v_forward*8 + '0 0 16');
+ if (this.skin_proj)
+ this.skin = this.skin_proj;
+ else
+ this.skin = 0;
+
+ // homing & missile duration
+ if (this.homing > 0)
+ {
+ setup_homing (proj_basespeed * proj_speed_mod);
+ }
+ else
+ {
+ this.think = sub_remove;
+ this.nextthink = time + 5;
+ }
+
+ setsize (this, ROCKET_MINS, ROCKET_MAXS);
+ setorigin (this, this.origin);
+ };
};
-
-// end dumptruck_ds grunt missle end
-
-
Return to the top of this page or return to the overview of this repo.
Diff qc/projectiles/spike.qc
diff --git a/qc/projectiles/spike.qc b/qc/projectiles/spike.qc
index ffd941f..99e2e66 100644
--- a/qc/projectiles/spike.qc
+++ b/qc/projectiles/spike.qc
@@ -2,222 +2,83 @@
// Nails
//======================================================================
-void() spike_touch;
-void() superspike_touch;
-
-//----------------------------------------------------------------------
-// launch_spike -- Used for both the player and the ogre
-//----------------------------------------------------------------------
-void(vector org, vector dir, float speed) launch_spike2 =
-{
- newmis = spawn ();
- newmis.owner = self;
- newmis.movetype = MOVETYPE_FLYMISSILE;
- newmis.solid = SOLID_BBOX;
-
- newmis.angles = vectoangles (dir);
-
- newmis.touch = spike_touch;
- newmis.classname = "spike";
- if (self.homing > 0)
- {
- SetupHoming (newmis, speed);
- }
- else
- {
- newmis.think = sub_remove;
- newmis.nextthink = time + 6;
- }
- setmodel (newmis, "progs/spike.mdl");
- setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
- setorigin (newmis, org);
-
- SetSpeed (newmis, dir, speed *
- (self.proj_speed_mod ? self.proj_speed_mod : 1));
-};
-
-void(vector org, vector dir) launch_spike =
-{
- launch_spike2 (org,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);
- 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)
- {
- if (self.classname == "player")
- {
- self.weapon = PlayerBestWeapon ();
- PlayerSetCurrentAmmo ();
- }
- 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);
- // seven Nailgun position fix - thanks to Greenwood -- dumptruck_ds
- launch_spike (self.origin + self.view_ofs +
- v_up * -8 +v_right * ox, dir);
-
- self.punchangle_x = -2;
-};
-
-void() spike_touch =
+//======================================================================
+// constants
+//======================================================================
+const float SPIKE_NORMAL_DAMAGE = 9; // direct damage; 9 is id1
+const float SPIKE_SUPER_DAMAGE = 18; // superspike direct damage; 18 is id1
+const float SPIKE_DUPER_DAMAGE = 36; // superduperspike direct; 36 is pd3
+const float SPIKE_SPLASH_DAMAGE = 36; // splash damage
+const float SPIKE_EXPLOD_DAMAGE = 36; // direct damage
+const float SPIKE_SPEED = 1000; // id1 player spikes move at 1000ups
+
+const vector SPIKE_MINS = '0 0 0'; // let's not change this -- CEV
+const vector SPIKE_MAXS = '0 0 0'; //
+
+//------------------------------------------------------------------------------
+class projectile_spike: base_projectile
{
- if (other == self.owner)
- return;
+ //--------------------------------------------------------------
+ // Touch is handled by base_projectile -- CEV
+ //--------------------------------------------------------------
- if (other.solid == SOLID_TRIGGER)
- // trigger field, do nothing
- return;
-
- if (pointcontents(self.origin) == CONTENT_SKY)
- {
- remove (self);
- return;
- }
-
- // hit something that bleeds
- if (other.takedamage)
- {
- spawn_touchblood (9);
- T_Damage (other, self, self.owner, 9);
- }
- else
+ //--------------------------------------------------------------
+ void() projectile_spike =
{
-
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- if (self.owner.snd_hit != __NULL__ && self.owner.snd_hit != "")
- {
- // dumptruck_ds
- sound (self, CHAN_WEAPON, self.owner.snd_hit,
- 1, ATTN_STATIC);
- WriteByte(MSG_BROADCAST, TE_GUNSHOT);
- }
-
- else if (self.classname == "wizspike")
- WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
- else if (self.classname == "knightspike")
- WriteByte (MSG_BROADCAST, TE_KNIGHTSPIKE);
+ this.classtype = CT_PROJECTILE_SPIKE;
+ this.classname = "spike";
+ this.movetype = MOVETYPE_FLYMISSILE;
+ this.solid = SOLID_BBOX;
+ this.explosive = parse_projexpl (projexpl, 0);
+ this.angles = vectoangles (this.velocity);
+
+ if (!this.proj_basespeed)
+ this.proj_basespeed = SPIKE_SPEED;
+
+ if (!this.direct_damage)
+ if (this.explosive)
+ this.direct_damage = SPIKE_EXPLOD_DAMAGE;
+ else
+ this.direct_damage = SPIKE_NORMAL_DAMAGE;
+
+ if (!this.splash_damage)
+ if (this.explosive)
+ this.splash_damage = SPIKE_SPLASH_DAMAGE;
+ else
+ this.splash_damage = 0;
+
+ // dumptruck_ds custom_mdls
+ if (this.mdl_proj != "")
+ setmodel (this, this.mdl_proj);
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 (other == self.owner)
- return;
-
- if (other.solid == SOLID_TRIGGER)
- // trigger field, do nothing
- return;
-
- if (pointcontents(self.origin) == CONTENT_SKY)
- {
- remove(self);
- return;
- }
+ // this is kinda wonky -- CEV
+ if (this.direct_damage == SPIKE_SUPER_DAMAGE)
+ // supernail
+ setmodel (this, "progs/s_spike.mdl");
+ else if (this.direct_damage == SPIKE_DUPER_DAMAGE)
+ // superdupernail
+ setmodel (this, "progs/lspike.mdl");
+ else
+ // regular nail
+ setmodel (this, "progs/spike.mdl");
+
+ // dumptruck_ds
+ if (this.skin_proj)
+ this.skin = this.skin_proj;
+ else
+ this.skin = 0;
- // hit something that bleeds
- if (other.takedamage)
- {
- spawn_touchblood (18);
- T_Damage (other, self, self.owner, 18);
- }
- else
- {
- // TODO CEV radiusdamage from spikes (for climbing purposes)
- T_RadiusDamage (self, self.owner, 40, world);
- if (self.owner.snd_hit != __NULL__ && self.owner.snd_hit != "")
+ if (this.homing > 0)
{
- // dumptruck_ds
- sound (self, CHAN_WEAPON, self.owner.snd_hit,
- 1, ATTN_STATIC);
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte(MSG_BROADCAST, TE_GUNSHOT);
+ setup_homing (proj_basespeed * proj_speed_mod);
}
else
{
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
+ this.think = sub_remove;
+ this.nextthink = time + 6;
}
- WriteCoord (MSG_BROADCAST, self.origin_x);
- WriteCoord (MSG_BROADCAST, self.origin_y);
- WriteCoord (MSG_BROADCAST, self.origin_z);
- }
- remove (self);
+ setsize (this, SPIKE_MINS, SPIKE_MAXS);
+ setorigin (this, this.origin);
+ };
};
-
-//----------------------------------------------------------------------
-// dumptruck_ds for Style 2 Ogre see ogre.qc
-//----------------------------------------------------------------------
-void() superduperspike_touch =
-{
- if (other == self.owner)
- return;
-
- if (other.solid == SOLID_TRIGGER)
- // trigger field, do nothing
- return;
-
- if (pointcontents(self.origin) == CONTENT_SKY)
- {
- remove (self);
- return;
- }
-
- // hit something that bleeds
- if (other.takedamage)
- {
- spawn_touchblood (36);
- T_Damage (other, self, self.owner, 36);
- sound (self, CHAN_VOICE, "fish/bite.wav", 1, ATTN_NORM);
- }
- 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);
-};
-
-
Return to the top of this page or return to the overview of this repo.
Diff qc/projectiles/voreball.qc
diff --git a/qc/projectiles/voreball.qc b/qc/projectiles/voreball.qc
new file mode 100644
index 0000000..ec4a84f
--- /dev/null
+++ b/qc/projectiles/voreball.qc
@@ -0,0 +1,98 @@
+//==============================================================================
+// vore / shalrath projectile
+//==============================================================================
+
+//======================================================================
+// constants
+//======================================================================
+const float VOREBALL_DIRECT_DAMAGE = 110;// only for zombies -- CEV
+const float VOREBALL_SPLASH_DAMAGE = 40;// splash damage; 120 is id1
+const float VOREBALL_SPEED = 400; // id1 400ups
+const float VOREBALL_HEALTH = 50; // slightly more difficult to destroy
+
+// found with FTE's sv_gameplayfix_setmodelrealbox
+const vector VOREBALL_MINS = '-16 -16 -16';
+const vector VOREBALL_MAXS = '16 16 16';
+
+//------------------------------------------------------------------------------
+class projectile_voreball: base_projectile_qcphys
+{
+ //--------------------------------------------------------------
+ virtual void() do_destroy =
+ {
+ // dprint ("projectile_lavaball::do_destroy: exploding...\n");
+ this.do_touch_explosive (this);
+ };
+
+ //--------------------------------------------------------------
+ // ShalMissileTouch
+ //--------------------------------------------------------------
+ virtual void(entity toucher) do_touch_explosive =
+ {
+ if (toucher.classtype == CT_MONSTER_ZOMBIE)
+ t_damage2 (toucher, this, this, direct_damage);
+
+ if (this.takedamage)
+ this.takedamage = DAMAGE_NO;
+
+ t_radiusdamage2 (this, this.owner, splash_damage, world);
+ sound (this, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
+
+ // BecomeExplosion
+ base_explosion::write_explosion (this.origin);
+ spawn (base_explosion, origin: this.origin);
+ remove (this);
+ };
+
+ //--------------------------------------------------------------
+ void() projectile_voreball =
+ {
+ this.classtype = CT_PROJECTILE_VOREBALL;
+ this.classname = "voreball";
+ this.movetype = MOVETYPE_FLYMISSILE;
+ this.solid = SOLID_BBOX;
+ this.explosive = TRUE;
+ this.health = VOREBALL_HEALTH;
+ this.takedamage = DAMAGE_YES;
+ this.angles = vectoangles (this.velocity);
+
+ // custom spin on projectile -- dumptruck_ds
+ if (!this.avelocity)
+ this.avelocity = '300 300 300';
+
+ if (!this.proj_basespeed)
+ this.proj_basespeed = VOREBALL_SPEED;
+
+ if (!this.direct_damage)
+ this.direct_damage = VOREBALL_DIRECT_DAMAGE;
+
+ if (!this.splash_damage)
+ this.splash_damage = VOREBALL_SPLASH_DAMAGE;
+
+ // dumptruck_ds custom_mdls
+ if (this.mdl_proj != "")
+ setmodel (this, this.mdl_proj);
+ else
+ setmodel (this, "progs/v_spike.mdl");
+
+ // dumptruck_ds
+ if (this.skin_proj)
+ this.skin = this.skin_proj;
+ else
+ this.skin = 0;
+
+ if (this.homing > 0)
+ {
+ setup_homing (proj_basespeed * proj_speed_mod);
+ }
+ else
+ {
+ // SetSpeed
+ this.think = sub_remove;
+ this.nextthink = time + 5;
+ }
+
+ setsize (this, VOREBALL_MINS, VOREBALL_MAXS);
+ setorigin (this, this.origin);
+ };
+};
Return to the top of this page or return to the overview of this repo.
Diff qc/projectiles/wizardspell.qc
diff --git a/qc/projectiles/wizardspell.qc b/qc/projectiles/wizardspell.qc
new file mode 100644
index 0000000..3de6b5b
--- /dev/null
+++ b/qc/projectiles/wizardspell.qc
@@ -0,0 +1,168 @@
+//==============================================================================
+// Wizard (Scrag) Magic Missile
+//==============================================================================
+
+//======================================================================
+// constants
+//======================================================================
+const float WIZMIS_DIRECT_DAMAGE = 9; // direct damage; 9 is id1
+const float WIZMIS_SPLASH_DAMAGE = 9; // splash damage
+const float WIZMIS_EXPLOD_DAMAGE = 50; // big damage. explody scrag should
+ // be beefy. dmg for direct & splash
+const float WIZMIS_SPEED = 600; // id1 magic missile speed 600ups
+
+const vector WIZMIS_MINS = '0 0 0'; // let's not change this -- CEV
+const vector WIZMIS_MAXS = '0 0 0'; //
+
+//======================================================================
+// This is a weird one. The Wizard spawns an entity with a think
+// function that then spawns the actual missile. So we're dealing with
+// two temporary entities: the projectile (wizardmissile), and the thing
+// that creates it (wizardspell). -- CEV
+//======================================================================
+
+//------------------------------------------------------------------------------
+class projectile_wizardmissile: base_projectile
+{
+ //--------------------------------------------------------------
+ // adapted from spike_touch -- CEV
+ //--------------------------------------------------------------
+ virtual void(entity toucher) do_touch =
+ {
+ if (toucher.takedamage)
+ {
+ spawn_touchblood (direct_damage);
+ t_damage2 (toucher, this, this.owner, direct_damage);
+ }
+ else
+ {
+ WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
+ if (this.owner.snd_hit != __NULL__ &&
+ this.owner.snd_hit != "")
+ {
+ // dumptruck_ds
+ sound (this, CHAN_WEAPON, this.owner.snd_hit,
+ 1, ATTN_STATIC);
+ WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
+ }
+ else
+ {
+ WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
+ }
+ WriteCoord (MSG_BROADCAST, this.origin_x);
+ WriteCoord (MSG_BROADCAST, this.origin_y);
+ WriteCoord (MSG_BROADCAST, this.origin_z);
+ }
+
+ remove (this);
+ };
+
+ //--------------------------------------------------------------
+ void() projectile_wizardmissile =
+ {
+ this.classtype = CT_PROJECTILE_WIZARDMISSILE;
+ this.classname = "wizspike";
+ this.movetype = MOVETYPE_FLYMISSILE;
+ this.solid = SOLID_BBOX;
+ this.explosive = parse_projexpl (this.projexpl, 0);
+ this.angles = vectoangles (this.velocity);
+
+ if (!this.proj_basespeed)
+ this.proj_basespeed = WIZMIS_SPEED;
+
+ if (!this.direct_damage)
+ if (this.explosive)
+ this.direct_damage = WIZMIS_EXPLOD_DAMAGE;
+ else
+ this.direct_damage = WIZMIS_DIRECT_DAMAGE;
+
+ if (!this.splash_damage)
+ if (this.explosive)
+ this.splash_damage = WIZMIS_EXPLOD_DAMAGE;
+ else
+ this.splash_damage = WIZMIS_SPLASH_DAMAGE;
+
+ // dumptruck_ds custom_mdls
+ if (this.mdl_proj != "")
+ setmodel (this, this.mdl_proj);
+ else
+ setmodel (this, "progs/w_spike.mdl");
+
+ // dumptruck_ds
+ if (this.skin_proj)
+ this.skin = this.skin_proj;
+ else
+ this.skin = 0;
+
+ if (this.homing > 0 || this.owner.homing > 0)
+ {
+ setup_homing (proj_basespeed * proj_speed_mod);
+ }
+ else
+ {
+ // SetSpeed
+ this.think = sub_remove;
+ this.nextthink = time + 5;
+ }
+
+ setsize (this, WIZMIS_MINS, WIZMIS_MAXS);
+ setorigin (this, this.origin);
+ };
+};
+
+//------------------------------------------------------------------------------
+class projectile_wizardspell: base_tempentity
+{
+ //==============================================================
+ // 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.
+ //==============================================================
+
+ //--------------------------------------------------------------
+ // Wizard missile think function
+ //--------------------------------------------------------------
+ virtual void() think =
+ {
+ // make sure owner still exists -- CEV
+ if (!this.owner)
+ {
+ remove (this);
+ return;
+ }
+
+ // make sure owner is still alive
+ if (this.owner.health > 0)
+ {
+ owner.effects = owner.effects | EF_MUZZLEFLASH;
+
+ makevectors (this.enemy.angles);
+ local vector dir = normalize ((this.enemy.origin - 13 *
+ this.movedir) - this.origin);
+
+ // SetSpeed (newmis, vec, projspeed);
+ dir *= min (this.proj_basespeed * (this.proj_speed_mod ?
+ this.proj_speed_mod : 1), frame_maxvelocity);
+
+ spawn (projectile_wizardmissile,
+ owner: this.owner,
+ enemy: this.enemy,
+ origin: this.origin,
+ velocity: dir,
+ proj_basespeed: this.proj_basespeed,
+ proj_speed_mod: this.proj_speed_mod,
+ projexpl: this.projexpl);
+ }
+
+ remove (this);
+ };
+
+ //--------------------------------------------------------------
+ void() projectile_wizardspell =
+ {
+ this.classtype = CT_TEMP_WIZARDSPELL;
+
+ setsize (this, '0 0 0', '0 0 0');
+ setorigin (this, this.origin);
+ };
+};
Return to the top of this page or return to the overview of this repo.
Diff qc/projectiles/zombiechunk.qc
diff --git a/qc/projectiles/zombiechunk.qc b/qc/projectiles/zombiechunk.qc
new file mode 100644
index 0000000..8af0583
--- /dev/null
+++ b/qc/projectiles/zombiechunk.qc
@@ -0,0 +1,77 @@
+//==============================================================================
+// Zombie grenade projectile
+//==============================================================================
+
+//======================================================================
+// constants
+//======================================================================
+const float ZCHUNK_DIRECT_DAMAGE = 10; // direct damage; 10 is id1
+ // zombie chunks don't splash
+const float ZCHUNK_SPEED = 600; // id1 default 600
+
+const vector ZCHUNK_MINS = '0 0 0'; // let's not change this -- CEV
+const vector ZCHUNK_MAXS = '0 0 0'; //
+
+//------------------------------------------------------------------------------
+class projectile_zombiechunk: base_projectile
+{
+ //--------------------------------------------------------------
+ // ZombieGrenadeTouch
+ //--------------------------------------------------------------
+ virtual void(entity toucher) do_touch =
+ {
+ if (toucher.takedamage)
+ {
+ // hardcoded 10 damage -- CEV
+ t_damage2 (toucher, this, this.owner, direct_damage);
+ sound (this, CHAN_WEAPON, "zombie/z_hit.wav",
+ 1, ATTN_NORM);
+ remove (this);
+ return;
+ }
+
+ // bounce sound
+ sound (this, CHAN_WEAPON, "zombie/z_miss.wav", 1, ATTN_NORM);
+ this.velocity = '0 0 0';
+ this.avelocity = '0 0 0';
+ this.touch = sub_remove;
+ };
+
+ //--------------------------------------------------------------
+ void() projectile_zombiechunk =
+ {
+ this.classtype = CT_PROJECTILE_ZOMBIECHUNK;
+ this.classname = "zgibs";
+ this.movetype = MOVETYPE_BOUNCE;
+ this.solid = SOLID_BBOX;
+ this.angles = vectoangles (this.velocity);
+
+ if (!this.avelocity)
+ this.avelocity = '3000 1000 2000';
+
+ if (!this.proj_basespeed)
+ this.proj_basespeed = ZCHUNK_SPEED;
+
+ if (!this.direct_damage)
+ this.direct_damage = ZCHUNK_DIRECT_DAMAGE;
+
+ // dumptruck_ds custom_mdls
+ if (this.mdl_proj != "")
+ setmodel (this, this.mdl_proj);
+ else
+ setmodel (this, "progs/zom_gib.mdl");
+
+ // dumptruck_ds
+ if (this.skin_proj)
+ this.skin = this.skin_proj;
+ else
+ this.skin = 0;
+
+ setsize (this, ZCHUNK_MINS, ZCHUNK_MAXS);
+ setorigin (this, this.origin);
+
+ // set missile duration
+ this.nextthink = time + 2.5;
+ this.think = sub_remove;
+ };
+};
Return to the top of this page or return to the overview of this repo.
Diff qc/triggers/changelevel.qc
diff --git a/qc/triggers/changelevel.qc b/qc/triggers/changelevel.qc
index 368d7bd..2e58f10 100644
--- a/qc/triggers/changelevel.qc
+++ b/qc/triggers/changelevel.qc
@@ -36,6 +36,7 @@ class trigger_changelevel: base_trigger
other = findfloat (world, ::classtype, CT_PLAYER);
while (other != world)
{
+ other.velocity = '0 0 0';
other.view_ofs = '0 0 0';
other.angles = other.v_angle = pos.mangle;
// turn this way immediately
@@ -46,8 +47,10 @@ class trigger_changelevel: base_trigger
other.movetype = MOVETYPE_NONE;
other.modelindex = 0;
setorigin (other, pos.origin);
- other = findfloat (other, ::classtype, CT_PLAYER);
fog_setFromEnt (other, pos);
+ // TODO CEV
+ other.SendFlags = 0xffffff;
+ other = findfloat (other, ::classtype, CT_PLAYER);
}
// Drake -- dumptruck_ds
@@ -64,6 +67,7 @@ class trigger_changelevel: base_trigger
cvar_set ("viewsize", val);
}
}
+
WriteByte (MSG_ALL, SVC_INTERMISSION);
};
@@ -80,13 +84,13 @@ class trigger_changelevel: base_trigger
if ((cvar("noexit") == 1) || ((cvar("noexit") == 2) &&
(mapname != "start")))
{
- T_Damage (toucher, this, this, 50000);
+ t_damage2 (toucher, this, this, 50000);
return;
}
if (coop || deathmatch)
{
- bprint (other.netname);
+ bprint (toucher.netname);
bprint (" exited the level\n");
}
Return to the top of this page or return to the overview of this repo.
Diff qc/triggers/cvarset.qc
diff --git a/qc/triggers/cvarset.qc b/qc/triggers/cvarset.qc
index 30bddfe..ce398e2 100644
--- a/qc/triggers/cvarset.qc
+++ b/qc/triggers/cvarset.qc
@@ -42,7 +42,7 @@ class trigger_cvarset: base_trigger
/*
virtual void(entity toucher) do_touch =
{
- if (this.cnt > time || toucher.health <= 0 ||
+ if (this.cnt > time || other.health <= 0 ||
toucher.classtype != CT_PLAYER)
{
return;
Return to the top of this page or return to the overview of this repo.
Diff qc/triggers/hurt.qc
diff --git a/qc/triggers/hurt.qc b/qc/triggers/hurt.qc
index 9793bda..36aff9d 100644
--- a/qc/triggers/hurt.qc
+++ b/qc/triggers/hurt.qc
@@ -57,7 +57,7 @@ class trigger_hurt: base_trigger
if (time < this.hurt_nextthink)
return;
// 1998-07-03 hurt_touch fix by Robert Field end
- T_Damage (toucher, this, this, this.dmg);
+ t_damage2 (toucher, this, this, this.dmg);
// 1998-07-03 hurt_touch fix by Robert Field start
// this.think = hurt_on;
// this.nextthink = time + 1;
Return to the top of this page or return to the overview of this repo.
Diff qc/triggers/look.qc
diff --git a/qc/triggers/look.qc b/qc/triggers/look.qc
index 5402d58..3637f81 100644
--- a/qc/triggers/look.qc
+++ b/qc/triggers/look.qc
@@ -44,7 +44,7 @@ class trigger_look: base_multiple
traceline (player_offset,
(player_offset + (v_forward * this.speed)),
- FALSE, other);
+ FALSE, toucher);
if (trace_ent.targetname == this.target)
{
Return to the top of this page or return to the overview of this repo.
Diff qc/triggers/monsterface.qc
diff --git a/qc/triggers/monsterface.qc b/qc/triggers/monsterface.qc
index e7c3b7f..4365508 100644
--- a/qc/triggers/monsterface.qc
+++ b/qc/triggers/monsterface.qc
@@ -17,14 +17,14 @@ class trigger_monsterface: base_trigger
// visibleToOther - returns 1 if the entity is visible to other,
// even if not infront ()
//--------------------------------------------------------------
- nonvirtual float(entity targ) newai_visible_to_other =
+ nonvirtual float(entity targ, entity toucher) newai_visible_to_other =
{
local vector spot1, spot2;
- spot1 = other.origin + other.view_ofs;
+ spot1 = toucher.origin + toucher.view_ofs;
spot2 = targ.origin + targ.view_ofs;
// see through other monsters
- traceline (spot1, spot2, TRUE, other);
+ traceline (spot1, spot2, TRUE, toucher);
if (trace_inopen && trace_inwater)
// sight line crossed contents
@@ -44,7 +44,7 @@ class trigger_monsterface: base_trigger
(FL_MONSTER | FL_FLY | FL_SWIM) != FL_MONSTER)
return;
- if (!newai_visible_to_other(toucher.enemy))
+ if (!newai_visible_to_other(toucher.enemy, toucher))
{
// enemy is hidden
// don't dodge around, just go straight
Return to the top of this page or return to the overview of this repo.
Diff qc/triggers/multiple.qc
diff --git a/qc/triggers/multiple.qc b/qc/triggers/multiple.qc
index 41d7083..d29459d 100644
--- a/qc/triggers/multiple.qc
+++ b/qc/triggers/multiple.qc
@@ -88,9 +88,9 @@ class base_multiple: base_trigger
};
//--------------------------------------------------------------
- // dumptruck_ds
+ // multi_killed; dumptruck_ds
//--------------------------------------------------------------
- virtual void() multi_killed =
+ virtual void() do_destroy =
{
// Supa, restore health and do nothing if we're still
// waiting to be activated
@@ -207,7 +207,7 @@ class base_multiple: base_trigger
objerror ("health and notouch don't make "
"sense\n");
this.max_health = this.health;
- this.th_die = this.multi_killed;
+ this.th_die = this.do_destroy;
this.takedamage = DAMAGE_YES;
this.solid = SOLID_BBOX;
// make sure it links into the world
Return to the top of this page or return to the overview of this repo.
Diff qc/triggers/push.qc
diff --git a/qc/triggers/push.qc b/qc/triggers/push.qc
index 59cff6e..02c689c 100644
--- a/qc/triggers/push.qc
+++ b/qc/triggers/push.qc
@@ -104,15 +104,13 @@ class base_trigger_push: base_trigger
//--------------------------------------------------------------
nonvirtual vector(vector org, entity tgt, float ht) calculatevelocity =
{
- local float grav, sdist, zdist, vs, vz, jumpheight;
+ local float sdist, zdist, vs, vz, jumpheight;
local vector sdir, torg;
local vector solution;
local float flighttime;
torg = tgt.origin + (tgt.mins + tgt.maxs) * 0.5;
- grav = autocvar (sv_gravity, PM_GRAVITY);
-
zdist = torg_z - org_z;
sdist = vlen (torg - org - zdist * '0 0 1');
sdir = normalize (torg - org - zdist * '0 0 1');
@@ -144,7 +142,7 @@ class base_trigger_push: base_trigger
*/
// push him so high... NOTE: sqrt(positive)!
- vz = sqrt (2 * grav * jumpheight);
+ vz = sqrt (2 * frame_gravity * jumpheight);
// we start with downwards velocity only if it's a downjump
// and the jump apex should be outside the jump!
@@ -153,7 +151,7 @@ class base_trigger_push: base_trigger
vz = -vz;
// equation "z(ti) = zdist"
- solution = solve_quadratic (0.5 * grav, -vz, zdist);
+ solution = solve_quadratic (0.5 * frame_gravity, -vz, zdist);
// ALWAYS solvable because jumpheight >= zdist
if (!solution_z)
// just in case it is not solvable due to roundoff
@@ -241,7 +239,7 @@ class base_trigger_push: base_trigger
this.movedir = this.calculatevelocity (toucher.origin,
this.enemy, this.height);
- if (toucher.classname == "grenade")
+ if (toucher.classtype == CT_PROJECTILE_GRENADE)
{
if (this.target && this.enemy)
toucher.velocity = this.movedir;
Return to the top of this page or return to the overview of this repo.
Diff qc/triggers/setgravity.qc
diff --git a/qc/triggers/setgravity.qc b/qc/triggers/setgravity.qc
index 330abdd..d0c599d 100644
--- a/qc/triggers/setgravity.qc
+++ b/qc/triggers/setgravity.qc
@@ -97,7 +97,7 @@ class trigger_setgravity: base_trigger
if (!this.gravity)
this.gravity = -1;
else
- this.gravity = ((this.gravity - 1) / 100);
+ this.gravity = ((this.gravity - 1) / 100);
sub_checkwaiting ();
};
Return to the top of this page or return to the overview of this repo.
Diff qc/triggers/take_weapon.qc
diff --git a/qc/triggers/take_weapon.qc b/qc/triggers/take_weapon.qc
index 9dfda6a..dc401e5 100644
--- a/qc/triggers/take_weapon.qc
+++ b/qc/triggers/take_weapon.qc
@@ -33,8 +33,8 @@ class trigger_take_weapon: base_multiple
toucher.items = toucher.items - (toucher.items & IT_SHELLS);
if (toucher.classtype == CT_PLAYER)
{
- PlayerSetCurrentAmmo ();
- PlayerBestWeapon ();
+ ((player)toucher).set_current_ammo ();
+ ((player)toucher).best_weapon ();
}
};
Return to the top of this page or return to the overview of this repo.
Diff qc/triggers/teleport.qc
diff --git a/qc/triggers/teleport.qc b/qc/triggers/teleport.qc
index 4687784..1f3be95 100644
--- a/qc/triggers/teleport.qc
+++ b/qc/triggers/teleport.qc
@@ -68,7 +68,7 @@ void() spawn_tdeath_touch =
if (self.owner.classtype != CT_PLAYER)
{
// other monsters explode themselves
- T_Damage (self.owner, self, self, 50000);
+ base_entity::t_damage2 (self.owner, self, self, 50000);
return;
}
// 1998-07-26 Pentagram telefrag fix by Zoid/Maddes end
@@ -85,7 +85,8 @@ void() spawn_tdeath_touch =
self.classname = "teledeath3";
other.invincible_finished = 0;
// kill player on spot
- T_Damage (other, self, self, 50000);
+ base_entity::t_damage2 (other, self, self,
+ 50000);
/*
// 1998-07-26 only telefrag player on spot
@@ -105,7 +106,7 @@ void() spawn_tdeath_touch =
self.classname = "teledeath2";
// 1998-07-26 Pentagram telefrag fix by
// Zoid/Maddes start
- T_Damage (self.owner, self, self, 50000);
+ base_entity::t_damage2 (self.owner, self, self, 50000);
}
return;
}
@@ -121,7 +122,7 @@ void() spawn_tdeath_touch =
}
if (other.health)
- T_Damage (other, self, self, 50000);
+ base_entity::t_damage2 (other, self, self, 50000);
};
//----------------------------------------------------------------------
Return to the top of this page or return to the overview of this repo.
Diff qc/triggers/void.qc
diff --git a/qc/triggers/void.qc b/qc/triggers/void.qc
index 41df9b4..3331d18 100644
--- a/qc/triggers/void.qc
+++ b/qc/triggers/void.qc
@@ -49,7 +49,8 @@ class trigger_void: base_trigger
// kills even with Pentagram, this took forever to
// figure out!! -- dumptruck_ds
toucher.invincible_finished = 0;
- T_Damage (toucher, this, this, toucher.health + 1000);
+ this.t_damage2 (toucher, this, this,
+ toucher.health + 1000);
if (toucher.flags & FL_MONSTER)
remove (toucher);
Return to the top of this page or return to the overview of this repo.
Diff qc/weapons.qc
diff --git a/qc/weapons.qc b/qc/weapons.qc
deleted file mode 100644
index e907511..0000000
--- a/qc/weapons.qc
+++ /dev/null
@@ -1,299 +0,0 @@
-//==============================================================================
-// WEAPONS.QC
-//==============================================================================
-
-void(entity mis, vector dir, float speed) SetSpeed =
-{
- if (cvar("sv_maxvelocity") > speed)
- {
- mis.velocity = dir * speed;
- }
- else
- {
- mis.velocity = dir * cvar("sv_maxvelocity");
- }
-};
-
-//----------------------------------------------------------------------
-vector() wall_velocity =
-{
- local vector vel;
-
- vel = normalize (self.velocity);
- vel = normalize (vel + v_up*(random()- 0.5) +
- v_right * (random() - 0.5));
- vel = vel + 2 * trace_plane_normal;
- vel = vel * 200;
-
- return vel;
-};
-
-//----------------------------------------------------------------------
-// SpawnMeatSpray
-//----------------------------------------------------------------------
-void(vector org, vector vel) SpawnMeatSpray =
-{
- local entity missile;
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_NOT;
-
- makevectors (self.angles);
-
- missile.velocity = vel;
- missile.velocity_z = missile.velocity_z + 250 + 50 * random ();
-
- missile.avelocity = '3000 1000 2000';
-
- // set missile duration
- missile.nextthink = time + 1;
- missile.think = sub_remove;
-
- setmodel (missile, "progs/zom_gib.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, org);
-};
-
-//----------------------------------------------------------------------
-// SpawnBlood
-//----------------------------------------------------------------------
-void(vector org, vector vel, float damage) SpawnBlood =
-{
- particle (org, vel * 0.1, 73, damage * 2);
-};
-
-//----------------------------------------------------------------------
-// spawn_touchblood
-//----------------------------------------------------------------------
-void(float damage) spawn_touchblood =
-{
- local vector vel;
-
- vel = wall_velocity() * 0.2;
- SpawnBlood (self.origin + vel* 0.01, vel, damage);
-};
-
-//----------------------------------------------------------------------
-// SpawnChunk
-//----------------------------------------------------------------------
-void(vector org, vector vel) SpawnChunk =
-{
- particle (org, vel * 0.02, 0, 10);
-};
-
-//======================================================================
-// Lightning
-//======================================================================
-
-//----------------------------------------------------------------------
-// LightningDamage
-//----------------------------------------------------------------------
-void(vector p1, vector p2, entity from, float damage) LightningDamage =
-{
- local entity e1, e2;
- local vector f;
-
- f = p2 - p1;
- normalize (f);
- f_x = 0 - f_y;
- f_y = f_x;
- f_z = 0;
- f = f * 16;
-
- e1 = e2 = world;
-
- traceline (p1, p2, FALSE, self);
- if (trace_ent.takedamage)
- {
- particle (trace_endpos, '0 0 100', 225, damage * 4);
- T_Damage (trace_ent, from, from, damage);
- if (self.classname == "player")
- {
- if (other.classname == "player")
- trace_ent.velocity_z += 400;
- }
- }
- e1 = trace_ent;
-
- traceline (p1 + f, p2 + f, FALSE, self);
- if (trace_ent != e1 && trace_ent.takedamage)
- {
- particle (trace_endpos, '0 0 100', 225, damage * 4);
- T_Damage (trace_ent, from, from, damage);
- }
- e2 = trace_ent;
-
- traceline (p1 - f, p2 - f, FALSE, self);
- if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
- {
- particle (trace_endpos, '0 0 100', 225, damage * 4);
- T_Damage (trace_ent, from, from, damage);
- }
-};
-
-void() W_FireLightning =
-{
- local vector org;
- local float cells;
-
- if (self.ammo_cells < 1)
- {
- if (self.classname == "player")
- {
- self.weapon = PlayerBestWeapon ();
- PlayerSetCurrentAmmo ();
- }
- return;
- }
-
- // explode if under water
- if (self.waterlevel > WATERLEVEL_FEET)
- {
- cells = self.ammo_cells;
- self.ammo_cells = 0;
- if (self.classname == "player")
- PlayerSetCurrentAmmo ();
- T_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;
-
- // TODO CEV
- org = self.origin + '0 0 16';
- // org = self.origin;
-
- traceline (org, org + v_forward * 600, TRUE, self);
-
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
- WriteEntity (MSG_BROADCAST, self);
- WriteCoord (MSG_BROADCAST, org_x);
- WriteCoord (MSG_BROADCAST, org_y);
- WriteCoord (MSG_BROADCAST, org_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);
-};
-
-/*
-===============================================================================
-
-PLAYER WEAPON USE
-
-===============================================================================
-*/
-
-//----------------------------------------------------------------------
-// SuperDamageSound
-// Plays sound if needed
-//----------------------------------------------------------------------
-void() SuperDamageSound =
-{
- if (self.super_damage_finished > time)
- {
- if (self.super_sound < time)
- {
- self.super_sound = time + 1;
- sound (self, CHAN_BODY, "items/damage3.wav",
- 1, ATTN_NORM);
- }
- }
- return;
-};
-
-//----------------------------------------------------------------------
-void() MissileHome =
-{
- local vector dir, vtemp;
- vtemp = self.enemy.origin + '0 0 10';
-
- if (self.enemy.health < 1)
- {
- remove (self);
- return;
- }
-
- dir = normalize (vtemp - self.origin);
- // can't do better than 100% homing
- if (self.homing < 1 && self.homing > 0)
- {
- // This finds a vector somewhere between the vector the
- // projectile is currently travelling on and the vector
- // that it would normally snap to for homing
- // homing = .25 means it will go 25% to the new direction,
- // but keep 75% of the original vector, resulting in a
- // wider turning range.
- dir = normalize ((dir * self.homing) +
- normalize(self.velocity * (1 - self.homing)));
- }
-
- if (!self.avelocity)
- self.angles = vectoangles (dir);
- SetSpeed (self, dir, self.proj_basespeed);
-
- if (self.homing > 0)
- {
- if (self.homing < 1 && self.attack_finished &&
- self.attack_finished < time)
- {
- // dprint("incrementing homing | ");
- // dprint("old: ");
- // dprint(ftos(self.homing));
- // dprint(" | new: ");
- self.homing = self.homing + 0.005;
- // dprint(ftos(self.homing));
- // dprint("\n");
- }
-
- self.nextthink = time + 0.2;
- self.think = MissileHome;
- }
-};
-
-//----------------------------------------------------------------------
-void(entity mis, float speed) SetupHoming =
-{
- local vector dir;
- local float dist, flytime, speedmod;
- if (self.proj_speed_mod > 1)
- {
- speedmod = 1 / self.proj_speed_mod;
- }
- else if (speed > 250)
- {
- speedmod = 1 / (speed / 250);
- }
- else
- {
- speedmod = 1;
- }
-
- dir = normalize ((self.enemy.origin + '0 0 10') - self.origin);
- dist = vlen (self.enemy.origin - self.origin);
- flytime = dist * 0.002 * speedmod;
- if (flytime < 0.1)
- flytime = 0.1;
-
- mis.enemy = self.enemy;
- mis.proj_basespeed = speed;
- mis.homing = self.homing;
- mis.nextthink = flytime + time;
- mis.think = MissileHome;
- if (self.waitmin > 0)
- {
- // store time to start increasing
- mis.attack_finished = time + self.waitmin;
- }
-};
Return to the top of this page or return to the overview of this repo.
Diff qc/world.qc
diff --git a/qc/world.qc b/qc/world.qc
index a7e9dd9..0153c20 100644
--- a/qc/world.qc
+++ b/qc/world.qc
@@ -2,11 +2,17 @@
// WORLD
//==============================================================================
-// globals
+//======================================================================
+// Globals
+//======================================================================
entity bodyque_head;
entity lastspawn;
+// float known_release; // unique ID for a release
+// float skill; // latched skill CVAR
-// prototypes
+//======================================================================
+// Prototypes / Compiler Forward Declarations
+//======================================================================
void() InitBodyQue;
//----------------------------------------------------------------------
@@ -469,9 +475,15 @@ void() worldspawn =
// custom map attributes
if (self.model == "maps/e1m8.bsp" && self.skip_id1_overrides == 0)
+ {
cvar_set ("sv_gravity", "100");
+ frame_gravity = 100.0;
+ }
else
+ {
cvar_set ("sv_gravity", "800");
+ frame_gravity = 800.0;
+ }
// No cutscene is active during worldspawn. Drake -- dumptruck_ds
cutscene = 0;
@@ -695,8 +707,17 @@ void() StartFrame =
if (!done_inhibition_summary)
PrintInhibitionSummary ();
+ // per-frame latched variables -- CEV
teamplay = cvar ("teamplay");
skill = cvar ("skill");
+ frame_airstep = autocvar (pm_airstep, TRUE);
+ frame_bigcoords = autocvar (sv_bigcoords, FALSE);
+ frame_clrun = autocvar (cl_run, FALSE);
+ frame_gravity = autocvar (sv_gravity, 800.0);
+ frame_maxvelocity = autocvar (sv_maxvelocity, 10000.0);
+ frame_nostep = autocvar (pm_nostep, FALSE);
+ frame_standardphysics = autocvar (pm_standardphysics, FALSE);
+
framecount = framecount + 1;
if (cleanUpClientStuff)
@@ -756,22 +777,3 @@ void(entity ent) CopyToBodyQue =
setsize (bodyque_head, ent.mins, ent.maxs);
bodyque_head = bodyque_head.owner;
};
-
-// TODO CEV based on code from Nuclide SDK
-/*
-void(void() spawnfunc) CheckSpawn =
-{
- if (spawnfunc)
- {
- // dprint (sprintf("CheckSpawn: creating %s\n",
- // self.classname));
- spawnfunc ();
- }
- else
- {
- // print (sprintf("CheckSpawn: cannot find entity class %s\n",
- // self.classname));
- remove (self);
- }
-};
-*/
Return to the top of this page or return to the overview of this repo.