]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Moar things to attic
authorJakob MG <jakob_mg@hotmail.com>
Mon, 10 Oct 2011 15:56:49 +0000 (17:56 +0200)
committerJakob MG <jakob_mg@hotmail.com>
Mon, 10 Oct 2011 15:56:49 +0000 (17:56 +0200)
18 files changed:
qcsrc/server/attic/ai.qc [deleted file]
qcsrc/server/attic/defs.qc [deleted file]
qcsrc/server/attic/fight.qc [deleted file]
qcsrc/server/attic/m_monsters.qc [deleted file]
qcsrc/server/attic/monster_zombie.qc [deleted file]
qcsrc/server/attic/monsters/ai.qc [new file with mode: 0644]
qcsrc/server/attic/monsters/defs.qc [new file with mode: 0644]
qcsrc/server/attic/monsters/fight.qc [new file with mode: 0644]
qcsrc/server/attic/monsters/m_monsters.qc [new file with mode: 0644]
qcsrc/server/attic/monsters/monster_zombie.qc [new file with mode: 0644]
qcsrc/server/attic/vehicles/bumblebee.qc [new file with mode: 0644]
qcsrc/server/attic/vehicles/collision.qc [new file with mode: 0644]
qcsrc/server/attic/vehicles/network.qc [new file with mode: 0644]
qcsrc/server/attic/verbstack.qc [new file with mode: 0644]
qcsrc/server/vehicles/bumblebee.qc [deleted file]
qcsrc/server/vehicles/collision.qc [deleted file]
qcsrc/server/vehicles/network.qc [deleted file]
qcsrc/server/verbstack.qc [deleted file]

diff --git a/qcsrc/server/attic/ai.qc b/qcsrc/server/attic/ai.qc
deleted file mode 100644 (file)
index 59989e7..0000000
+++ /dev/null
@@ -1,891 +0,0 @@
-void() movetarget_f;
-void() t_movetarget;
-void() FoundTarget;
-
-float MONSTER_WANDER = 64; // disable wandering around
-float MONSTER_APPEAR = 128; // spawn invisible, and appear when triggered
-
-.float ismonster;
-.float monsterawaitingteleport; // avoid awaking monsters in teleport rooms
-
-// 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;
-
-/*
-
-.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
-//
-//float current_yaw;
-
-float(float v) anglemod =
-{
-       v = v - 360 * floor(v / 360);
-       return v;
-}
-
-/*
-==============================================================================
-
-MOVETARGET CODE
-
-The angle of the movetarget effects standing and bowing direction, but has no effect on movement, which allways 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');
-}
-
-/*QUAKED path_corner (0.5 0.3 0) (-8 -8 -8) (8 8 8)
-Monsters will continue walking towards the next target corner.
-*/
-void() path_corner =
-{
-       movetarget_f ();
-}
-
-/*
-=============
-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 =
-{
-       entity temp;
-
-       if (other.health < 1)
-               return;
-       if (other.movetarget != self)
-               return;
-
-       if (other.enemy)
-               return;         // fighting, not following a path
-
-       temp = self;
-       self = other;
-       other = temp;
-
-       /* PLEASE FIX THE SOUND CHANNEL BEFORE ACTIVATING THIS
-       if (self.classname == "monster_ogre")
-               sound (self, CHAN_VOICE, "ogre/ogdrag.wav", 1, ATTN_IDLE);// play chainsaw drag sound
-       */
-
-//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;
-       }
-}
-
-void() monster_wanderpaththink =
-{
-       vector v, v1;
-       float b, c;
-       self.nextthink = time + random() * 10 + 1;
-       if (self.owner.health < 1) // dead, also handled in death code
-       {
-               self.owner.movetarget = world;
-               remove(self);
-               return;
-       }
-       b = -1;
-       c = 10;
-       while (c > 0)
-       {
-               c = c - 1;
-               v = randomvec();
-               traceline(self.owner.origin, v * 1024 + self.owner.origin, FALSE, self);
-               v = trace_endpos - (normalize(v) * 16) - self.owner.origin;
-               if (vlen(v) > b)
-               {
-                       b = vlen(v);
-                       v1 = v;
-               }
-       }
-       setorigin(self, v1 + self.owner.origin);
-       self.owner.ideal_yaw = vectoyaw(self.origin - self.owner.origin);
-}
-
-void() monster_wanderpathtouch =
-{
-       if (other.health < 1)
-               return;
-       if (other.movetarget != self)
-               return;
-
-       if (other.enemy)
-               return;         // fighting, not following a path
-
-       /* PLEASE FIX THE SOUND CHANNEL BEFORE ACTIVATING THIS
-       if (other.classname == "monster_ogre")
-               sound (other, CHAN_VOICE, "ogre/ogdrag.wav", 1, ATTN_IDLE);// play chainsaw drag sound
-       */
-       monster_wanderpaththink();
-}
-
-void() monster_spawnwanderpath =
-{
-       newmis = spawn();
-       newmis.classname = "monster_wanderpath";
-       newmis.solid = SOLID_TRIGGER;
-       newmis.touch = monster_wanderpathtouch;
-       setsize (newmis, '-8 -8 -8', '8 8 8');
-       newmis.think = monster_wanderpaththink;
-       newmis.nextthink = time + random() * 10 + 1;
-       newmis.owner = self;
-       self.goalentity = self.movetarget = newmis;
-}
-
-void() monster_checkbossflag =
-{
-//#NO AUTOCVARS START
-#if 0
-       float healthboost;
-       float r;
-
-       // monsterbosses cvar or spawnflag 64 causes a monster to be a miniboss
-       if ((self.spawnflags & 64) || (random() * 100 < cvar("monsterbosspercent")))
-       {
-               self.radsuit_finished = time + 1000000000;
-               r = random() * 4;
-               if (r < 2)
-               {
-                       self.super_damage_finished = time + 1000000000;
-                       healthboost = 30 + self.health * 0.5;
-                       self.effects = self.effects | (EF_FULLBRIGHT | EF_BLUE);
-               }
-               if (r >= 1)
-               {
-                       healthboost = 30 + self.health * bound(0.5, skill * 0.5, 1.5);
-                       self.effects = self.effects | (EF_FULLBRIGHT | EF_RED);
-                       self.healthregen = max(self.healthregen, min(skill * 10, 30));
-               }
-               self.health = self.health + healthboost;
-               self.max_health = self.health;
-               self.bodyhealth = self.bodyhealth * 2 + healthboost;
-               do
-               {
-                       self.colormod_x = random();
-                       self.colormod_y = random();
-                       self.colormod_z = random();
-                       self.colormod =  normalize(self.colormod);
-               }
-               while (self.colormod_x > 0.6 && self.colormod_y > 0.6 && self.colormod_z > 0.6);
-       }
-#endif
-//#NO AUTOCVARS END
-}
-
-
-//============================================================================
-
-/*
-=============
-range
-
-returns the range catagorization of an entity reletive to self
-0      melee range, will become hostile even if back is turned
-1      visibility and infront, or visibility and show hostile
-2      infront and show hostile
-3      only triggered by damage
-=============
-*/
-float(entity targ) range =
-{
-       float r;
-       r = vlen ((self.origin + self.view_ofs) - (targ.origin + targ.view_ofs));
-       if (r < 120)
-               return RANGE_MELEE;
-       if (r < 500)
-               return RANGE_NEAR;
-       if (r < 2000) // increased from 1000 for DP
-               return RANGE_MID;
-       return RANGE_FAR;
-}
-
-/*
-=============
-visible
-
-returns 1 if the entity is visible to self, even if not infront ()
-=============
-*/
-float (entity targ) visible =
-{
-       if (vlen(targ.origin - self.origin) > 5000) // long traces are slow
-               return FALSE;
-
-       traceline ((self.origin + self.view_ofs), (targ.origin + targ.view_ofs), 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 =
-{
-       float dot;
-
-       makevectors (self.angles);
-       dot = normalize (targ.origin - self.origin) * v_forward;
-
-       return (dot > 0.3);
-}
-// returns 0 if not infront, or the dotproduct if infront
-float(vector dir, entity targ) infront2 =
-{
-       float dot;
-
-       dir = normalize(dir);
-       dot = normalize (targ.origin - self.origin) * dir;
-
-       if (dot >= 0.3) return dot; // infront
-       return 0;
-}
-
-
-//============================================================================
-
-/*
-===========
-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 =
-{
-       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() th_sightsound;
-
-void() SightSound =
-{
-       if (self.health < 1)
-               return;
-       // skill 5 does not play sight sounds, instead you only hear the appear sound as they are about to attack
-       if (skill >= 5)
-       if (self.classname != "monster_hellfish")
-               return;
-
-       if (self.th_sightsound)
-               self.th_sightsound();
-}
-
-void() FoundTarget =
-{
-       if (self.health < 1 || !self.th_run)
-               return;
-       if (self.enemy.health < 1 || !self.enemy.takedamage)
-               return;
-       if (self.enemy.classname == "player")
-       {
-               // let other monsters see this monster for a while
-               sight_entity = self;
-               sight_entity_time = time + 0.1;
-       }
-
-       self.show_hostile = time + 1;           // wake up other monsters
-
-       SightSound ();
-       HuntTarget ();
-}
-
-/*
-//float checkplayertime;
-entity lastcheckplayer;
-entity havocbot_list;
-
-
-entity() checkplayer =
-{
-       entity check;
-       float worldcount;
-       // we can just fallback on checkclient if there are no bots
-       if (!havocbot_list)
-               return checkclient();
-*/
-       /*
-       if (time < checkplayertime)
-       {
-               traceline(self.origin + self.view_ofs, lastcheckplayer.origin + lastcheckplayer.view_ofs, TRUE, self);
-               if (trace_fraction == 1)
-                       return lastcheckplayer;
-               if (trace_ent == lastcheckplayer)
-                       return lastcheckplayer;
-       }
-       checkplayertime = time + 0.1;
-       */
-/*
-       check = lastcheckplayer;
-       worldcount = 0;
-       c = 0;
-       do
-       {
-               c = c + 1;
-               check = findfloat(check, havocattack, TRUE);
-               if (check.classname == "player" || check.classname == "turretbase")
-               {
-                       traceline(self.origin + self.view_ofs, check.origin + check.view_ofs, TRUE, self);
-                       if (trace_fraction == 1)
-                               return lastcheckplayer = check;
-                       if (trace_ent == check)
-                               return lastcheckplayer = check;
-               }
-               else if (check == world)
-               {
-                       worldcount = worldcount + 1;
-                       if (worldcount >= 2)
-                               return lastcheckplayer = check;
-               }
-       }
-       while(check != lastcheckplayer && c < 100);
-       return world;
-}
-*/
-
-/*
-===========
-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;
-float() FindTarget =
-{
-       entity client;
-       float r;
-
-       if (self.health < 1)
-               return FALSE;
-
-       // if the first or second spawnflag bit is set, the monster will only
-       // wake up on really seeing the player, not another monster getting angry
-
-       if (self.spawnflags & 3)
-       {
-               // don't wake up on seeing another monster getting angry
-               client = checkclient ();
-               if (!client)
-                       return FALSE;   // current check entity isn't in PVS
-       }
-       else
-       {
-               if (sight_entity_time >= time)
-               {
-                       client = sight_entity;
-                       if (client.enemy == self.enemy)
-                               return TRUE;
-               }
-               else
-               {
-                       client = checkclient ();
-                       if (!client)
-                               return FALSE;   // current check entity isn't in PVS
-               }
-       }
-
-       if (client == self.enemy)
-               return FALSE;
-
-       if (client.flags & FL_NOTARGET)
-               return FALSE;
-
-#if 0
-       if (client.items & IT_INVISIBILITY)
-               return FALSE;
-#endif
-
-       // on skill 5 the monsters usually ignore the player and remain ghostlike
-       if (skill >= 5)
-       if (self.classname != "monster_hellfish")
-       if (random() < 0.99)
-               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)
-       {
-               // LordHavoc: was if ( /* client.show_hostile < time || */ !infront (client))
-               if (client.show_hostile < time && !infront (client))
-                       return FALSE;
-       }
-
-       //
-       // got one
-       //
-
-       if (client.model == "")
-               return FALSE;
-       self.enemy = client;
-       if (self.enemy.classname != "player" && self.enemy.classname != "turretbase")
-       {
-               self.enemy = self.enemy.enemy;
-               if (self.enemy.classname != "player" && self.enemy.classname != "turretbase")
-               {
-                       self.enemy = world;
-                       return FALSE;
-               }
-       }
-
-       FoundTarget ();
-
-       return TRUE;
-}
-
-
-//=============================================================================
-
-void(float dist) ai_forward =
-{
-       walkmove (self.angles_y, dist);
-}
-
-void(float dist) ai_back =
-{
-       walkmove ( (self.angles_y+180), dist);
-}
-
-
-void(float a) monster_setalpha;
-
-/*
-=============
-ai_pain
-
-stagger back a bit
-=============
-*/
-void(float dist) ai_pain =
-{
-       if (self.health < 1)
-               return;
-       ai_back (dist);
-}
-
-/*
-=============
-ai_painforward
-
-stagger back a bit
-=============
-*/
-void(float dist) ai_painforward =
-{
-       if (self.health < 1)
-               return;
-       walkmove (self.ideal_yaw, dist);
-}
-
-/*
-=============
-ai_walk
-
-The monster is walking it's beat
-=============
-*/
-void(float dist) ai_walk =
-{
-       if (self.health < 1)
-               return;
-
-       movedist = dist;
-
-       // check for noticing a player
-       if (self.oldenemy.takedamage)
-       if (self.oldenemy.health >= 1)
-       {
-               self.enemy = self.oldenemy;
-               self.oldenemy = world;
-               FoundTarget();
-               monster_setalpha(0);
-               return;
-       }
-       if (self.enemy)
-       {
-               if (self.enemy.takedamage)
-               {
-                       if (self.enemy.health >= 1)
-                       {
-                               FoundTarget();
-                               monster_setalpha(0);
-                               return;
-                       }
-                       else
-                               self.enemy = world;
-               }
-               else
-                       self.enemy = world;
-       }
-
-       self.findtarget = TRUE;
-
-       movetogoal (dist);
-       monster_setalpha(0);
-}
-
-
-/*
-=============
-ai_stand
-
-The monster is staying in one place for a while, with slight angle turns
-=============
-*/
-void() ai_stand =
-{
-       if (self.health < 1)
-               return;
-       if (self.enemy)
-       {
-               if (self.enemy.takedamage)
-               {
-                       if (self.enemy.health >= 1)
-                       {
-                               FoundTarget();
-                               monster_setalpha(0);
-                               return;
-                       }
-                       else
-                               self.enemy = world;
-               }
-               else
-                       self.enemy = world;
-       }
-       self.findtarget = TRUE;
-
-       if (time > self.pausetime)
-       {
-               self.th_walk ();
-               monster_setalpha(0);
-               return;
-       }
-
-// change angle slightly
-
-       monster_setalpha(0);
-}
-
-/*
-=============
-ai_turn
-
-don't move, but turn towards ideal_yaw
-=============
-*/
-void() ai_turn =
-{
-       if (self.enemy)
-       {
-               if (self.enemy.takedamage)
-               {
-                       if (self.enemy.health >= 1)
-                       {
-                               FoundTarget();
-                               monster_setalpha(0);
-                               return;
-                       }
-                       else
-                               self.enemy = world;
-               }
-               else
-                       self.enemy = world;
-       }
-       self.findtarget = TRUE;
-
-       ChangeYaw ();
-       monster_setalpha(0);
-}
-
-//=============================================================================
-
-/*
-=============
-ChooseTurn
-=============
-*/
-void(vector pDestvec) ChooseTurn =
-{
-       vector dir, newdir;
-
-       dir = self.origin - pDestvec;
-
-       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 =
-{
-       float delta;
-
-       delta = anglemod(self.angles_y - self.ideal_yaw);
-       if (delta > 45 && delta < 315)
-               return FALSE;
-       return TRUE;
-}
-
-
-//=============================================================================
-
-.float() th_checkattack;
-
-
-
-/*
-=============
-ai_run
-
-The monster has an enemy it is trying to kill
-=============
-*/
-void(float dist) ai_run =
-{
-       float ofs;
-       if (self.health < 1)
-               return;
-       movedist = dist;
-       // see if the enemy is dead
-       if (self.enemy.health < 1 || self.enemy.takedamage == DAMAGE_NO)
-       {
-               self.enemy = world;
-               // FIXME: look all around for other targets
-               if (self.oldenemy.health >= 1 && self.oldenemy.takedamage)
-               {
-                       self.enemy = self.oldenemy;
-                       self.oldenemy = world;
-                       HuntTarget ();
-               }
-               else
-               {
-                       if (self.movetarget)
-                               self.th_walk ();
-                       else
-                               self.th_stand ();
-                       return;
-               }
-       }
-
-       // wake up other monsters
-       self.show_hostile = time + 1;
-
-       // check knowledge of enemy
-       enemy_range = range(self.enemy);
-
-       self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
-       ChangeYaw ();
-
-       if (self.attack_state == AS_MELEE)
-       {
-               //dprint ("ai_run_melee\n");
-               //Turn and close until within an angle to launch a melee attack
-               if (FacingIdeal())
-               {
-                       self.th_melee ();
-                       self.attack_state = AS_STRAIGHT;
-               }
-               return;
-       }
-       else if (self.attack_state == AS_MISSILE)
-       {
-               //dprint ("ai_run_missile\n");
-               //Turn in place until within an angle to launch a missile attack
-               if (FacingIdeal())
-               if (self.th_missile ())
-                       self.attack_state = AS_STRAIGHT;
-               return;
-       }
-
-       if (self.th_checkattack())
-               return;                                 // beginning an attack
-
-       if (visible(self.enemy))
-               self.search_time = time + 5;
-       else if (coop)
-       {
-               // look for other coop players
-               if (self.search_time < time)
-                       self.findtarget = TRUE;
-       }
-
-       if (self.attack_state == AS_SLIDING)
-       {
-               //dprint ("ai_run_slide\n");
-               //Strafe sideways, but stay at aproximately the same range
-               if (self.lefty)
-                       ofs = 90;
-               else
-                       ofs = -90;
-
-               if (walkmove (self.ideal_yaw + ofs, movedist))
-                       return;
-
-               self.lefty = !self.lefty;
-
-               walkmove (self.ideal_yaw - ofs, movedist);
-       }
-
-       // head straight in
-       movetogoal (dist);              // done in C code...
-}
-
diff --git a/qcsrc/server/attic/defs.qc b/qcsrc/server/attic/defs.qc
deleted file mode 100644 (file)
index 1982142..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-.entity movetarget;
-.float pausetime;
-
-.void()         th_stand;
-.void()         th_walk;
-.void()         th_run;
-.float()        th_missile; // LordHavoc: changed from void() to float(), returns true if attacking
-.void()         th_melee;
-//.void(entity attacker, float damage, float damgtype, string dethtype)           th_pain; // TODO Xonotic uses event_damage
-//.void()         th_die; // TODO never called directly by Xonotic
-.entity         oldenemy;               // mad at this player before taking damage
-entity  newmis;                 // launch_spike sets this after spawning it
-
-// range values
-float   RANGE_MELEE                             = 0;
-float   RANGE_NEAR                              = 1;
-float   RANGE_MID                               = 2;
-float   RANGE_FAR                               = 3;
-
-float DMG_KNIGHT_MELEE_BASE           =    0;
-float DMG_KNIGHT_MELEE_RANDOM1        =    3;
-float DMG_KNIGHT_MELEE_RANDOM2        =    3;
-float DMG_KNIGHT_MELEE_RANDOM3        =    3;
-
-.float          show_hostile; 
-       // set to time+0.2 whenever a client fires a
-       // weapon or takes damage.  Used to alert
-       // monsters that otherwise would let the player go
-
-float movedist;
-.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 SKILL4_MINALPHA         = 0.4;
-
-float monsterwander;
-//#NO AUTOCVARS START
-/*
-        monsterwander = cvar("monsterwander");
-        // monsterwander is always on in skill 5
-        if (skill >= 5)
-                monsterwander = TRUE;
-*/
-//#NO AUTOCVARS END
-
-.float candrown;
-
-.void(vector org, float bodydamage, float armordamage, vector vel, float damgtype) bleedfunc;
-void(vector org, float bodydamage, float armordamage, vector vel, float damgtype) genericbleedfunc;
diff --git a/qcsrc/server/attic/fight.qc b/qcsrc/server/attic/fight.qc
deleted file mode 100644 (file)
index a8fcd8e..0000000
+++ /dev/null
@@ -1,252 +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.
-
-*/
-
-void SUB_AttackFinished (float normal)
-{
-       self.cnt = 0;           // refire count for nightmare
-       if (skill < 3)
-               ATTACK_FINISHED(self) = time + normal;
-}
-
-float CanDamage(entity targ, entity inflictor)
-{
-       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;
-}
-
-float(float v) anglemod;
-
-void(vector dest) ChooseTurn;
-
-void() ai_face;
-
-
-float enemy_range;
-
-
-//=============================================================================
-
-/*
-===========
-GenericCheckAttack
-
-The player is in view, so decide to move or launch an attack
-Returns FALSE if movement should continue
-============
-*/
-float() GenericCheckAttack =
-{
-       vector spot1, spot2;
-       entity targ;
-       float chance;
-
-       if (self.health < 1)
-               return FALSE;
-       targ = self.enemy;
-
-       if (vlen(targ.origin - self.origin) > 5000) // long traces are slow
-               return FALSE;
-
-// see if any entities are in the way of the shot
-       spot1 = self.origin + self.view_ofs;
-       spot2 = targ.origin + targ.view_ofs;
-
-       traceline (spot1, spot2, FALSE, self);
-
-       if (trace_ent != targ)
-               return FALSE; // don't have a clear shot
-
-       if (trace_inopen && trace_inwater)
-               return FALSE; // sight line crossed contents
-
-       if (enemy_range == RANGE_MELEE)
-       {       // melee attack
-               if (self.th_melee)
-               {
-                       self.th_melee ();
-                       return TRUE;
-               }
-       }
-
-// missile attack
-       if (time < ATTACK_FINISHED(self))
-               return FALSE;
-
-       if (!self.th_missile)
-               return FALSE;
-
-       if (enemy_range == RANGE_FAR)
-               return FALSE;
-
-       if (enemy_range == RANGE_MELEE)
-       {
-               chance = 0.9;
-               ATTACK_FINISHED(self) = 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)
-       if (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
-=============
-*/
-float (entity targ) visible;
-float(entity targ) infront;
-float(entity targ) range;
-
-void(float d) ai_charge =
-{
-       if (self.health < 1)
-               return;
-       ai_face ();
-       movetogoal (d);         // done in C code...
-}
-
-void() ai_charge_side =
-{
-       if (self.health < 1)
-               return;
-       vector dtemp;
-       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 =
-{
-       vector delta;
-       float ldmg;
-
-       if (self.health < 1)
-               return;
-       if (!self.enemy)
-               return;         // removed before stroke
-
-       delta = self.enemy.origin - self.origin;
-
-       if (vlen(delta) > 60)
-               return;
-
-       ldmg = DMG_KNIGHT_MELEE_BASE + DMG_KNIGHT_MELEE_RANDOM1 * random();
-       ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM2 * random();
-       ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM3 * random();
-       traceline(self.origin, self.enemy.origin, FALSE, self);
-
-       Damage (self.enemy, self, self, ldmg, self.projectiledeathtype, trace_endpos, '0 0 0'); // TODO add force to monster melee attacks?
-}
-
-
-void() ai_melee_side =
-{
-       vector delta;
-       float ldmg;
-
-       if (self.health < 1)
-               return;
-       if (!self.enemy)
-               return;         // removed before stroke
-
-       ai_charge_side();
-
-       delta = self.enemy.origin - self.origin;
-
-       if (vlen(delta) > 60)
-               return;
-       if (!CanDamage (self.enemy, self))
-               return;
-       ldmg = DMG_KNIGHT_MELEE_BASE + DMG_KNIGHT_MELEE_RANDOM1 * random();
-       ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM2 * random();
-       ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM3 * random();
-       traceline(self.origin, self.enemy.origin, FALSE, self);
-       Damage (self.enemy, self, self, ldmg, self.projectiledeathtype, trace_endpos, '0 0 0');
-}
-
diff --git a/qcsrc/server/attic/m_monsters.qc b/qcsrc/server/attic/m_monsters.qc
deleted file mode 100644 (file)
index 3e160d9..0000000
+++ /dev/null
@@ -1,475 +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>
-// }
-
-.float ismonster;
-
-.float modelindex2;
-
-/*
-================
-monster_use
-
-Using a monster makes it angry at the current activator
-LordHavoc: using a monster with the spawnflag 'Appear' makes it appear
-================
-*/
-void() monster_use =
-{
-       if (self.enemy)
-               return;
-       if (self.health < 1)
-               return;
-       if (self.mdl)
-       if (self.spawnflags & MONSTER_APPEAR)
-       {
-               self.nextthink = time + 0.1;
-               self.spawnflags = self.spawnflags - MONSTER_APPEAR;
-               self.solid = SOLID_SLIDEBOX;
-               self.takedamage = DAMAGE_AIM;
-               //self.movetype = MOVETYPE_STEP;
-               self.model = self.mdl;
-               self.mdl = "";
-               self.modelindex = self.modelindex2;
-               self.modelindex2 = 0;
-               //setorigin(self, self.origin + '0 0 1');
-               spawn_tdeath(self.origin, self, self.origin);
-               return;
-       }
-
-#if 0
-       if (activator.items & IT_INVISIBILITY)
-               return;
-#endif
-       if (activator.flags & FL_NOTARGET)
-               return;
-       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;
-}
-
-void() monster_appearsetup =
-{
-       if ((self.spawnflags & MONSTER_APPEAR) == 0)
-               return;
-       self.mdl = self.model;
-       self.modelindex2 = self.modelindex;
-       self.modelindex = 0;
-       self.solid = SOLID_NOT;
-       self.takedamage = DAMAGE_NO;
-       //self.movetype = MOVETYPE_NONE;
-       self.nextthink = -1;
-       self.model = "";
-}
-
-/*
-================
-monster_setalpha
-
-Sets relative alpha of monster in skill 4 mode.
-================
-*/
-void(float a) monster_setalpha =
-{
-       if (skill < 4 || self.classname == "monster_hellfish")
-       {
-               self.alpha = 1.0;
-               return;
-       }
-
-       if (skill >= 5)
-       {
-               // randomly forget enemy, this makes monsters randomly return to their normal ghostlike state
-               if (a == 0)
-               if (self.enemy)
-               if (random() < 0.1)
-                       self.enemy = world;
-               // randomly blink (playing the same alarming sound as if attacking)
-               if (self.enemy == world)
-               {
-                       a = 0;
-                       if (time >= 0.3) // don't blink during the init process because it might become permanent
-                       if (random() < 0.005)
-                       {
-                               // blink for an instant, this causes the appear sound, alarming the player as if under attack
-                               /* PLEASE FIX THE SOUND CHANNEL BEFORE ACTIVATING THIS
-                               sound(self, CHAN_AUTO, "wizard/wsight.wav", 1, ATTN_NORM);
-                               */
-                               a = 1;
-                       }
-               }
-               // if ghosted, become non-solid and immune to damage
-               if (a <= 0 || self.enemy == world)
-               {
-                       self.solid = SOLID_NOT;
-                       self.takedamage = DAMAGE_NO;
-               }
-               else
-               {
-                       // if unghosting, make sure we have an enemy, otherwise stay ghosted (even if blinking) so we can't be shot while blinking
-                       /* PLEASE FIX THE SOUND CHANNEL BEFORE ACTIVATING THIS
-                       if (self.solid != SOLID_SLIDEBOX)
-                               sound(self, CHAN_AUTO, "wizard/wsight.wav", 1, ATTN_NORM);
-                       */
-                       self.solid = SOLID_SLIDEBOX;
-                       self.takedamage = DAMAGE_AIM;
-               }
-       }
-       self.alpha = SKILL4_MINALPHA + (1 - SKILL4_MINALPHA) * bound(0, a, 1);
-}
-
-/*
-================
-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;
-
-       activator = self.enemy;
-       SUB_UseTargets ();
-}
-
-
-void() monsterinwall =
-{
-       entity e;
-       if (!autocvar_developer)
-               return;
-       // this is handy for level designers,
-       // puts a spikey ball where the error is...
-       e = spawn();
-       setorigin(e, self.origin);
-       setmodel (e, "models/ebomb.mdl");
-       e.movetype = MOVETYPE_NONE;
-       e.solid = SOLID_NOT;
-       e.think = SUB_Null;
-       e.nextthink = -1;
-       e.scale = 16;
-}
-
-//============================================================================
-
-void() walkmonster_start_go =
-{
-       self.origin_z = self.origin_z + 1; // raise off floor a bit
-
-       tracebox(self.origin, self.mins, self.maxs, self.origin, TRUE, self);
-       if (trace_startsolid)
-       {
-               dprint("walkmonster in wall at: ");
-               dprint(vtos(self.origin));
-               dprint("\n");
-               monsterinwall();
-               droptofloor();
-       }
-       else
-       {
-               droptofloor();
-               if (!walkmove(0,0))
-               {
-                       dprint("walkmonster in wall at: ");
-                       dprint(vtos(self.origin));
-                       dprint("\n");
-                       monsterinwall();
-               }
-       }
-
-       //self.cantrigger = TRUE;
-
-       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 (monsterwander)
-               self.spawnflags = self.spawnflags | MONSTER_WANDER;
-
-       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
-               {
-                       if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
-                       {
-                               monster_spawnwanderpath();
-                               self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
-                               self.th_walk ();
-                       }
-                       else
-                       {
-                               self.pausetime = 99999999;
-                               self.th_stand ();
-                       }
-               }
-       }
-       else
-       {
-               if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
-               {
-                       monster_spawnwanderpath();
-                       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
-       self.nextthink = self.nextthink + random()*0.5 + 0.1;
-       self.iscreature = TRUE;
-       self.damagedbycontents = TRUE;
-
-       force_retouch = 2; // mainly to detect teleports
-
-       monster_appearsetup();
-}
-
-
-void() walkmonster_start =
-{
-       self.candrown = 1; // this is turned off by some monsters like zombies
-       // delay drop to floor to make sure all doors have been spawned
-       // spread think times so they don't all happen at same time
-       self.nextthink = time + random()*0.5 + 0.3;
-       self.think = walkmonster_start_go;
-       total_monsters = total_monsters + 1;
-       self.bot_attack = TRUE;
-       self.frags = 2; // actually just used to get havocbots to attack it...
-       self.bleedfunc = genericbleedfunc;
-       self.ismonster = TRUE;
-
-       monster_setalpha (0);
-}
-
-
-
-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");
-               monsterinwall();
-       }
-
-       //self.cantrigger = TRUE;
-
-       if (monsterwander)
-               self.spawnflags = self.spawnflags | MONSTER_WANDER;
-
-       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
-               {
-                       if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
-                       {
-                               monster_spawnwanderpath();
-                               self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
-                               self.th_walk ();
-                       }
-                       else
-                       {
-                               self.pausetime = 99999999;
-                               self.th_stand ();
-                       }
-               }
-       }
-       else
-       {
-               if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
-               {
-                       monster_spawnwanderpath();
-                       self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
-                       self.th_walk ();
-               }
-               else
-               {
-                       self.pausetime = 99999999;
-                       self.th_stand ();
-               }
-       }
-       self.iscreature = TRUE;
-       self.damagedbycontents = TRUE;
-
-       force_retouch = 2; // mainly to detect teleports
-
-       monster_appearsetup();
-}
-
-void() flymonster_start =
-{
-       self.candrown = 1;
-       // spread think times so they don't all happen at same time
-       self.nextthink = time + random()*0.5 + 0.1;
-       self.think = flymonster_start_go;
-       total_monsters = total_monsters + 1;
-       self.bot_attack = TRUE;
-       self.frags = 2; // actually just used to get havocbots to attack it...
-       self.bleedfunc = genericbleedfunc;
-       self.ismonster = TRUE;
-
-       monster_setalpha (0);
-}
-
-
-void() swimmonster_start_go =
-{
-       if (deathmatch)
-       {
-               remove(self);
-               return;
-       }
-
-       //self.cantrigger = TRUE;
-
-       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 (monsterwander)
-               self.spawnflags = self.spawnflags | MONSTER_WANDER;
-
-       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
-               {
-                       if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
-                       {
-                               monster_spawnwanderpath();
-                               self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
-                               self.th_walk ();
-                       }
-                       else
-                       {
-                               self.pausetime = 99999999;
-                               self.th_stand ();
-                       }
-               }
-       }
-       else
-       {
-               if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
-               {
-                       monster_spawnwanderpath();
-                       self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
-                       self.th_walk ();
-               }
-               else
-               {
-                       self.pausetime = 99999999;
-                       self.th_stand ();
-               }
-       }
-       self.iscreature = TRUE;
-       self.damagedbycontents = TRUE;
-
-       force_retouch = 2; // mainly to detect teleports
-
-       monster_appearsetup();
-}
-
-void() swimmonster_start =
-{
-       // spread think times so they don't all happen at same time
-       self.candrown = 0;
-       self.nextthink = time + random()*0.5 + 0.1;
-       self.think = swimmonster_start_go;
-       total_monsters = total_monsters + 1;
-       self.bot_attack = TRUE;
-       self.frags = 2; // actually just used to get havocbots to attack it...
-       self.bleedfunc = genericbleedfunc;
-       self.ismonster = TRUE;
-
-       monster_setalpha(0);
-}
-
-void(vector org, float bodydamage, float armordamage, vector force, float damgtype) genericbleedfunc =
-{
-        vector v;
-        v = '0 0 0' - force * 0.05;
-        if (armordamage > 0)
-                te_spark(org, v, armordamage * 3);
-        if (bodydamage > 0)
-                te_blood(org, v, bodydamage);
-}
diff --git a/qcsrc/server/attic/monster_zombie.qc b/qcsrc/server/attic/monster_zombie.qc
deleted file mode 100644 (file)
index c95c2ea..0000000
+++ /dev/null
@@ -1,575 +0,0 @@
-//#define MONSTES_ENABLED
-#ifdef MONSTES_ENABLED
-
-float autocvar_g_monster_zombie_attack_run_damage;
-float autocvar_g_monster_zombie_attack_run_delay;
-float autocvar_g_monster_zombie_attack_run_force;
-float autocvar_g_monster_zombie_attack_run_hitrange;
-float autocvar_g_monster_zombie_attack_run_range;
-float autocvar_g_monster_zombie_attack_stand_damage;
-float autocvar_g_monster_zombie_attack_stand_delay;
-float autocvar_g_monster_zombie_attack_stand_force;
-float autocvar_g_monster_zombie_attack_stand_range;
-float autocvar_g_monster_zombie_health;
-float autocvar_g_monster_zombie_idle_timer_max;
-float autocvar_g_monster_zombie_idle_timer_min;
-float autocvar_g_monster_zombie_movespeed;
-float autocvar_g_monster_zombie_respawntime;
-float autocvar_g_monster_zombie_stopspeed;
-float autocvar_g_monster_zombie_targetrange;
-float autocvar_g_monster_zombie_turnspeed;
-float autocvar_g_monsters;
-
-
-#define zombie_anim_attackleap         0
-#define zombie_anim_attackrun1         1
-#define zombie_anim_attackrun2         2
-#define zombie_anim_attackrun3         3
-#define zombie_anim_attackstanding1    4
-#define zombie_anim_attackstanding2    5
-#define zombie_anim_attackstanding3    6
-#define zombie_anim_blockend           7
-#define zombie_anim_blockstart         8
-#define zombie_anim_deathback1         9
-#define zombie_anim_deathback2         10
-#define zombie_anim_deathback3         11
-#define zombie_anim_deathfront1        12
-#define zombie_anim_deathfront2        13
-#define zombie_anim_deathfront3        14
-#define zombie_anim_deathleft1         15
-#define zombie_anim_deathleft2         16
-#define zombie_anim_deathright1        17
-#define zombie_anim_deathright2        18
-#define zombie_anim_idle               19
-#define zombie_anim_painback1          20
-#define zombie_anim_painback2          21
-#define zombie_anim_painfront1         22
-#define zombie_anim_painfront2         23
-#define zombie_anim_runbackwards       24
-#define zombie_anim_runbackwardsleft   25
-#define zombie_anim_runbackwardsright  26
-#define zombie_anim_runforward         27
-#define zombie_anim_runforwardleft     28
-#define zombie_anim_runforwardright    29
-#define zombie_anim_spawn              30
-
-#define ZOMBIE_MIN                                      '-18 -18 -25'
-#define ZOMBIE_MAX                                      '18 18 47'
-
-#define ZV_IDLE     10
-
-#define ZV_PATH     100
-#define ZV_HUNT     200
-
-#define ZV_ATTACK_FIND  10
-#define ZV_ATTACK_RUN   20
-#define ZV_ATTACK_STAND 30
-
-#define ZV_PATH2 10000
-
-//.entity verbs_idle;
-//.entity verbs_attack;
-//.entity verbs_move;
-
-//.float  state_timeout;
-//.void() monster_state;
-#define MONSTERFLAG_NORESPAWN 2
-
-void zombie_spawn();
-
-float zombie_scoretarget(entity trg)
-{
-    float  tmp;
-    vector ang1;
-
-    if (trg.takedamage == DAMAGE_AIM)
-    if not (trg.flags & FL_NOTARGET)
-    if (trg.deadflag == DEAD_NO)
-    if (trg.team != self.team)
-    {
-        if((self.origin_z - trg.origin_z) < 128)
-        {
-            ang1 = normalize(self.origin - trg.origin);
-            tmp = vlen(ang1 - v_forward);
-            if(tmp > 1.5)
-            {
-                traceline(self.origin + '0 0 47',trg.origin + '0 0 32',MOVE_NORMAL,self);
-                if(trace_ent != trg)
-                    return 0;
-
-                return (autocvar_g_monster_zombie_targetrange - vlen(self.origin - trg.origin)) * tmp;
-            }
-            else if(self.enemy == trg)
-                return (autocvar_g_monster_zombie_targetrange - vlen(self.origin - trg.origin)) * tmp;
-        }
-    }
-
-    return 0;
-}
-
-void zombie_corpse_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-    //dprint("zombie_corpse_damage\n");
-    Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
-
-    self.health -= damage;
-
-    if(self.health < 0)
-    {
-        Violence_GibSplash(self, 1, 1, attacker);
-        remove(self);
-    }
-}
-
-void zombie_die(vector dir)
-{
-    vector v;
-    float f;
-
-    entity dummy;
-
-    dummy = spawn();
-    setmodel(dummy,"models/monsters/zombie.dpm");
-    setorigin(dummy, self.origin);
-    dummy.velocity  = self.velocity;
-    dummy.movetype  = MOVETYPE_BOUNCE;
-    dummy.think     = SUB_Remove;
-    dummy.nextthink = time + 3;
-    dummy.health    = 50;
-    dummy.takedamage = DAMAGE_YES;
-    dummy.event_damage = zombie_corpse_damage;
-    dummy.solid      = SOLID_CORPSE;
-    setsize(dummy,self.mins,self.maxs);
-
-    SUB_SetFade(dummy,time + 5,2);
-
-
-    v = normalize(self.origin - dir);
-    f = vlen(v_forward - v) - 1;
-    if(f > 0.5)
-        dummy.frame = zombie_anim_deathfront1 + rint(random() * 2);
-    else if(f < 0.5)
-        dummy.frame = zombie_anim_deathback1 + rint(random() * 2);
-    else
-    {
-        f = vlen(v_right - v) - 1;
-        if(f > 0.5)
-            dummy.frame = zombie_anim_deathright1 + rint(random() * 2);
-        else if(f < 0.5)
-            dummy.frame = zombie_anim_deathleft1 + rint(random() * 2);
-    }
-
-
-    if(self.spawnflags & MONSTERFLAG_NORESPAWN)
-    {
-        self.think = SUB_Remove;
-        self.nextthink = time;
-        return;
-    }
-
-    setmodel(self,"");
-    self.solid          = SOLID_NOT;
-    self.takedamage     = DAMAGE_NO;
-    self.event_damage   = SUB_Null;
-    self.enemy          = world;
-    self.think          = zombie_spawn;
-    self.nextthink      = time + autocvar_g_monster_zombie_respawntime;
-    self.pain_finished  = self.nextthink;
-}
-
-void zombie_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-
-    vector v;
-    float f;
-
-    v = normalize(self.origin - hitloc);
-    f = vlen(v_forward - v) - 1;
-
-
-    self.health -= damage;
-    self.velocity = self.velocity + force;
-    if(self.health <= 0)
-    {
-        zombie_die(hitloc);
-        return;
-    }
-
-    Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
-
-       if (damage > 50)
-               Violence_GibSplash_At(hitloc, force * -0.1, 3, 1, self, attacker);
-       if (damage > 100)
-               Violence_GibSplash_At(hitloc, force * -0.2, 3, 1, self, attacker);
-
-    if (time > self.pain_finished)
-    {
-        if(f < 0.5)
-        {
-            if(random() < 0.5)
-                self.frame = zombie_anim_painback1;
-            else
-                self.frame = zombie_anim_painback2;
-        }
-        else
-        {
-            if(random() < 0.5)
-                self.frame = zombie_anim_painfront1;
-            else
-                self.frame = zombie_anim_painfront2;
-        }
-
-        self.pain_finished = time + 0.36;
-    }
-}
-
-.vector bvec;
-.float bvec_time;
-
-void zombie_move()
-{
-    vector real_angle;
-    float vz, tdiff, tspeed;
-
-    tdiff = time - self.zoomstate;
-    tspeed = tdiff * autocvar_g_monster_zombie_turnspeed;
-    vz = self.velocity_z;
-    self.zoomstate = time;
-
-    if(self.bvec_time < time)
-    {
-        self.bvec_time = time + 0.2;
-        self.bvec = steerlib_beamsteer(steerlib_attract2(self.moveto,0.5,500,0.95),512,32,34,64);
-    }
-
-    if(self.enemy)
-        self.moveto = self.enemy.origin;
-    else
-        self.moveto = self.origin + v_forward;
-
-    self.steerto = normalize(steerlib_attract2(self.moveto,0.5,500,0.95) + self.bvec);
-
-    self.angles_y = safeangle(self.angles_y);
-    real_angle = vectoangles(self.steerto) - self.angles;
-    self.angles_y += bound(-10, real_angle_y, 10);
-
-    if(vlen(self.origin - self.moveto) > 64)
-    {
-        movelib_move_simple(v_forward ,autocvar_g_monster_zombie_movespeed,0.6);
-        if(time > self.pain_finished)
-            if(self.attack_finished_single < time)
-                self.frame = zombie_anim_runforward;
-    }
-    else
-    {
-        movelib_beak_simple(autocvar_g_monster_zombie_stopspeed);
-        if(time > self.pain_finished)
-            if(self.attack_finished_single < time)
-                self.frame = zombie_anim_idle;
-    }
-
-    self.velocity_z = vz;
-    self.steerto = self.origin;
-}
-
-float zombie_verb_idle_roam(float eval)
-{
-    switch (eval)
-    {
-    case VCM_EVAL:
-
-        if(self.enemy)
-            return VS_CALL_NO;
-
-        return verb.verb_static_value;
-
-    case VCM_DO:
-
-        self.moveto = v_forward * 128;
-        self.steerto = v_forward; //steerlib_beamsteer(v_forward,512,32,34,64);
-
-        return VS_CALL_YES_DOING;
-    }
-
-    return VS_CALL_YES_DONE;
-}
-
-float zombie_verb_idle_stand(float eval)
-{
-    switch (eval)
-    {
-    case VCM_EVAL:
-
-        if(self.enemy)
-            return VS_CALL_NO;
-
-        return verb.verb_static_value;
-
-    case VCM_DO:
-
-        self.moveto   = self.origin;
-        self.frame    = zombie_anim_idle;
-        self.velocity = '0 0 0';
-
-        return VS_CALL_YES_DOING;
-    }
-
-    return VS_CALL_YES_DONE;
-}
-
-float zombie_verb_idle(float eval)
-{
-    switch (eval)
-    {
-    case VCM_EVAL:
-
-        if(self.enemy)
-            return VS_CALL_NO;
-
-        return verb.verb_static_value;
-
-    case VCM_DO:
-        float t;
-
-        t = autocvar_g_monster_zombie_idle_timer_max -  autocvar_g_monster_zombie_idle_timer_min;
-        t = autocvar_g_monster_zombie_idle_timer_min + (random() * t);
-
-        if(random() < 0.5)
-            verbstack_push(self.verbs_idle, zombie_verb_idle_roam,  ZV_IDLE + 1, t, self);
-        else
-            verbstack_push(self.verbs_idle, zombie_verb_idle_stand, ZV_IDLE + 1, 0.1, self);
-
-        return VS_CALL_YES_DOING;
-    }
-
-    return VS_CALL_YES_DONE;
-}
-
-float zombie_verb_attack_findtarget(float eval)
-{
-    switch (eval)
-    {
-    case VCM_EVAL:
-        if(self.enemy)
-            return VS_CALL_NO;
-
-        return verb.verb_static_value;
-
-    case VCM_DO:
-
-        entity trg, best_trg;
-        float trg_score, best_trg_score;
-
-        trg = findradius(self.origin,autocvar_g_monster_zombie_targetrange);
-        while(trg)
-        {
-            trg_score = zombie_scoretarget(trg);
-            if(trg_score > best_trg_score)
-            {
-                best_trg = trg;
-                best_trg_score = trg_score;
-            }
-
-            trg = trg.chain;
-        }
-
-        if(best_trg)
-        {
-            self.enemy = best_trg;
-            dprint("Selected: ",best_trg.netname, " as target.\n");
-        }
-
-        return VS_CALL_YES_DOING;
-    }
-
-    return VS_CALL_YES_DONE;
-}
-
-void zombie_runattack_damage()
-{
-    entity oldself;
-    oldself = self;
-    self = self.owner;
-
-    if(vlen(self.origin - self.enemy.origin) > autocvar_g_monster_zombie_attack_run_hitrange)
-        return;
-
-    if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6)
-        return;
-
-    Damage(self.enemy, self, self, autocvar_g_monster_zombie_attack_run_damage, DEATH_TURRET, self.enemy.origin, normalize(self.enemy.origin - self.origin)  * autocvar_g_monster_zombie_attack_run_force);
-
-    self = oldself;
-    self.think = SUB_Remove;
-    self.nextthink = time;
-}
-
-float zombie_verb_attack_run(float eval)
-{
-    switch (eval)
-    {
-    case VCM_EVAL:
-        if not (self.enemy)
-            return VS_CALL_NO;
-
-        if(self.attack_finished_single > time)
-            return VS_CALL_NO;
-
-        if(vlen(self.origin - self.enemy.origin) > autocvar_g_monster_zombie_attack_run_range)
-            return VS_CALL_NO;
-
-        if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6)
-            return VS_CALL_NO;
-
-        return verb.verb_static_value;
-
-    case VCM_DO:
-        entity pain;
-        pain = spawn();
-        pain.owner = self;
-        pain.think = zombie_runattack_damage;
-        pain.nextthink = time + autocvar_g_monster_zombie_attack_run_delay;
-
-        self.attack_finished_single = time + 0.7;
-        self.frame = zombie_anim_attackrun1 + rint(random() * 2);
-
-        return VS_CALL_YES_DOING;
-    }
-
-    return VS_CALL_YES_DONE;
-}
-
-void zombie_standattack_damage()
-{
-    //entity oldself;
-    //oldself = self;
-    //self = self.owner;
-
-    setorigin(self,self.owner.origin + v_forward * 32);
-    RadiusDamage(self, self.owner, autocvar_g_monster_zombie_attack_stand_damage,autocvar_g_monster_zombie_attack_stand_damage,16,self, autocvar_g_monster_zombie_attack_stand_force,DEATH_TURRET,world);
-    //float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity ignore, float forceintensity, float deathtype, entity directhitentity)
-
-
-    //self = oldself;
-    self.think = SUB_Remove;
-    self.nextthink = time;
-}
-
-float zombie_verb_attack_stand(float eval)
-{
-    switch (eval)
-    {
-    case VCM_EVAL:
-        if not (self.enemy)
-            return VS_CALL_NO;
-
-        if(self.attack_finished_single > time)
-            return VS_CALL_NO;
-
-        if(vlen(self.origin - self.enemy.origin) > autocvar_g_monster_zombie_attack_stand_range)
-            return VS_CALL_NO;
-
-        if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.8)
-            return VS_CALL_NO;
-
-        return verb.verb_static_value;
-
-    case VCM_DO:
-        entity pain;
-        pain = spawn();
-        pain.owner = self;
-        pain.think = zombie_runattack_damage;
-        pain.nextthink = time + autocvar_g_monster_zombie_attack_stand_delay;
-
-        self.attack_finished_single = time + 0.7;
-        self.frame = zombie_anim_attackstanding1 + rint(random() * 1);
-        dprint("frame:",ftos(self.frame),"\n");
-
-        return VS_CALL_YES_DOING;
-    }
-
-    return VS_CALL_YES_DONE;
-}
-
-void zombie_think()
-{
-    self.angles_x *= -1;
-    makevectors(self.angles);
-    self.angles_x *= -1;
-
-    if (zombie_scoretarget(self.enemy) == 0)
-        self.enemy = world;
-
-    verbstack_pop(self.verbs_attack);
-    //verbstack_pop(self.verbs_move);
-
-    if not (self.enemy)
-        verbstack_pop(self.verbs_idle);
-
-    zombie_move();
-
-    if(self.enemy)
-        self.nextthink = time;
-    else
-        self.nextthink = time + 0.2;
-}
-
-void zombie_spawn()
-{
-    setmodel(self,"models/monsters/zombie.dpm");
-
-    self.solid          = SOLID_BBOX;
-    self.takedamage     = DAMAGE_AIM;
-    self.event_damage   = zombie_damage;
-    self.enemy          = world;
-    self.frame          = zombie_anim_spawn;
-    self.think          = zombie_think;
-    self.nextthink      = time + 2.1;
-    self.pain_finished  = self.nextthink;
-    self.movetype       = MOVETYPE_WALK;
-    self.health         = autocvar_g_monster_zombie_health;
-    self.velocity       = '0 0 0';
-    self.angles         = self.pos2;
-    self.moveto         = self.origin;
-    self.flags          = FL_MONSTER;
-
-    setorigin(self,self.pos1);
-    setsize(self,ZOMBIE_MIN,ZOMBIE_MAX);
-}
-
-
-void spawnfunc_monster_zombie()
-{
-    if not(autocvar_g_monsters)
-    {
-        remove(self);
-        return;
-    }
-
-    precache_model("models/monsters/zombie.dpm");
-
-
-    self.verbs_idle   = spawn();
-    self.verbs_attack = spawn();
-
-    self.verbs_idle.owner = self;
-    self.verbs_attack.owner = self;
-
-    self.think      = zombie_spawn;
-    self.nextthink  = time + 2;
-
-    traceline(self.origin + '0 0 10', self.origin - '0 0 32', MOVE_WORLDONLY, self);
-
-    self.pos1 = trace_endpos;
-    self.pos2 = self.angles;
-    self.team = MAX_SHOT_DISTANCE -1;
-
-    verbstack_push(self.verbs_idle, zombie_verb_idle, ZV_IDLE,0 , self);
-
-    verbstack_push(self.verbs_attack, zombie_verb_attack_findtarget, ZV_ATTACK_FIND,0 , self);
-    verbstack_push(self.verbs_attack, zombie_verb_attack_run, ZV_ATTACK_RUN,0 , self);
-    verbstack_push(self.verbs_attack, zombie_verb_attack_stand, ZV_ATTACK_STAND,0 , self);
-
-}
-
-#endif // MONSTES_ENABLED
diff --git a/qcsrc/server/attic/monsters/ai.qc b/qcsrc/server/attic/monsters/ai.qc
new file mode 100644 (file)
index 0000000..59989e7
--- /dev/null
@@ -0,0 +1,891 @@
+void() movetarget_f;
+void() t_movetarget;
+void() FoundTarget;
+
+float MONSTER_WANDER = 64; // disable wandering around
+float MONSTER_APPEAR = 128; // spawn invisible, and appear when triggered
+
+.float ismonster;
+.float monsterawaitingteleport; // avoid awaking monsters in teleport rooms
+
+// 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;
+
+/*
+
+.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
+//
+//float current_yaw;
+
+float(float v) anglemod =
+{
+       v = v - 360 * floor(v / 360);
+       return v;
+}
+
+/*
+==============================================================================
+
+MOVETARGET CODE
+
+The angle of the movetarget effects standing and bowing direction, but has no effect on movement, which allways 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');
+}
+
+/*QUAKED path_corner (0.5 0.3 0) (-8 -8 -8) (8 8 8)
+Monsters will continue walking towards the next target corner.
+*/
+void() path_corner =
+{
+       movetarget_f ();
+}
+
+/*
+=============
+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 =
+{
+       entity temp;
+
+       if (other.health < 1)
+               return;
+       if (other.movetarget != self)
+               return;
+
+       if (other.enemy)
+               return;         // fighting, not following a path
+
+       temp = self;
+       self = other;
+       other = temp;
+
+       /* PLEASE FIX THE SOUND CHANNEL BEFORE ACTIVATING THIS
+       if (self.classname == "monster_ogre")
+               sound (self, CHAN_VOICE, "ogre/ogdrag.wav", 1, ATTN_IDLE);// play chainsaw drag sound
+       */
+
+//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;
+       }
+}
+
+void() monster_wanderpaththink =
+{
+       vector v, v1;
+       float b, c;
+       self.nextthink = time + random() * 10 + 1;
+       if (self.owner.health < 1) // dead, also handled in death code
+       {
+               self.owner.movetarget = world;
+               remove(self);
+               return;
+       }
+       b = -1;
+       c = 10;
+       while (c > 0)
+       {
+               c = c - 1;
+               v = randomvec();
+               traceline(self.owner.origin, v * 1024 + self.owner.origin, FALSE, self);
+               v = trace_endpos - (normalize(v) * 16) - self.owner.origin;
+               if (vlen(v) > b)
+               {
+                       b = vlen(v);
+                       v1 = v;
+               }
+       }
+       setorigin(self, v1 + self.owner.origin);
+       self.owner.ideal_yaw = vectoyaw(self.origin - self.owner.origin);
+}
+
+void() monster_wanderpathtouch =
+{
+       if (other.health < 1)
+               return;
+       if (other.movetarget != self)
+               return;
+
+       if (other.enemy)
+               return;         // fighting, not following a path
+
+       /* PLEASE FIX THE SOUND CHANNEL BEFORE ACTIVATING THIS
+       if (other.classname == "monster_ogre")
+               sound (other, CHAN_VOICE, "ogre/ogdrag.wav", 1, ATTN_IDLE);// play chainsaw drag sound
+       */
+       monster_wanderpaththink();
+}
+
+void() monster_spawnwanderpath =
+{
+       newmis = spawn();
+       newmis.classname = "monster_wanderpath";
+       newmis.solid = SOLID_TRIGGER;
+       newmis.touch = monster_wanderpathtouch;
+       setsize (newmis, '-8 -8 -8', '8 8 8');
+       newmis.think = monster_wanderpaththink;
+       newmis.nextthink = time + random() * 10 + 1;
+       newmis.owner = self;
+       self.goalentity = self.movetarget = newmis;
+}
+
+void() monster_checkbossflag =
+{
+//#NO AUTOCVARS START
+#if 0
+       float healthboost;
+       float r;
+
+       // monsterbosses cvar or spawnflag 64 causes a monster to be a miniboss
+       if ((self.spawnflags & 64) || (random() * 100 < cvar("monsterbosspercent")))
+       {
+               self.radsuit_finished = time + 1000000000;
+               r = random() * 4;
+               if (r < 2)
+               {
+                       self.super_damage_finished = time + 1000000000;
+                       healthboost = 30 + self.health * 0.5;
+                       self.effects = self.effects | (EF_FULLBRIGHT | EF_BLUE);
+               }
+               if (r >= 1)
+               {
+                       healthboost = 30 + self.health * bound(0.5, skill * 0.5, 1.5);
+                       self.effects = self.effects | (EF_FULLBRIGHT | EF_RED);
+                       self.healthregen = max(self.healthregen, min(skill * 10, 30));
+               }
+               self.health = self.health + healthboost;
+               self.max_health = self.health;
+               self.bodyhealth = self.bodyhealth * 2 + healthboost;
+               do
+               {
+                       self.colormod_x = random();
+                       self.colormod_y = random();
+                       self.colormod_z = random();
+                       self.colormod =  normalize(self.colormod);
+               }
+               while (self.colormod_x > 0.6 && self.colormod_y > 0.6 && self.colormod_z > 0.6);
+       }
+#endif
+//#NO AUTOCVARS END
+}
+
+
+//============================================================================
+
+/*
+=============
+range
+
+returns the range catagorization of an entity reletive to self
+0      melee range, will become hostile even if back is turned
+1      visibility and infront, or visibility and show hostile
+2      infront and show hostile
+3      only triggered by damage
+=============
+*/
+float(entity targ) range =
+{
+       float r;
+       r = vlen ((self.origin + self.view_ofs) - (targ.origin + targ.view_ofs));
+       if (r < 120)
+               return RANGE_MELEE;
+       if (r < 500)
+               return RANGE_NEAR;
+       if (r < 2000) // increased from 1000 for DP
+               return RANGE_MID;
+       return RANGE_FAR;
+}
+
+/*
+=============
+visible
+
+returns 1 if the entity is visible to self, even if not infront ()
+=============
+*/
+float (entity targ) visible =
+{
+       if (vlen(targ.origin - self.origin) > 5000) // long traces are slow
+               return FALSE;
+
+       traceline ((self.origin + self.view_ofs), (targ.origin + targ.view_ofs), 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 =
+{
+       float dot;
+
+       makevectors (self.angles);
+       dot = normalize (targ.origin - self.origin) * v_forward;
+
+       return (dot > 0.3);
+}
+// returns 0 if not infront, or the dotproduct if infront
+float(vector dir, entity targ) infront2 =
+{
+       float dot;
+
+       dir = normalize(dir);
+       dot = normalize (targ.origin - self.origin) * dir;
+
+       if (dot >= 0.3) return dot; // infront
+       return 0;
+}
+
+
+//============================================================================
+
+/*
+===========
+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 =
+{
+       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() th_sightsound;
+
+void() SightSound =
+{
+       if (self.health < 1)
+               return;
+       // skill 5 does not play sight sounds, instead you only hear the appear sound as they are about to attack
+       if (skill >= 5)
+       if (self.classname != "monster_hellfish")
+               return;
+
+       if (self.th_sightsound)
+               self.th_sightsound();
+}
+
+void() FoundTarget =
+{
+       if (self.health < 1 || !self.th_run)
+               return;
+       if (self.enemy.health < 1 || !self.enemy.takedamage)
+               return;
+       if (self.enemy.classname == "player")
+       {
+               // let other monsters see this monster for a while
+               sight_entity = self;
+               sight_entity_time = time + 0.1;
+       }
+
+       self.show_hostile = time + 1;           // wake up other monsters
+
+       SightSound ();
+       HuntTarget ();
+}
+
+/*
+//float checkplayertime;
+entity lastcheckplayer;
+entity havocbot_list;
+
+
+entity() checkplayer =
+{
+       entity check;
+       float worldcount;
+       // we can just fallback on checkclient if there are no bots
+       if (!havocbot_list)
+               return checkclient();
+*/
+       /*
+       if (time < checkplayertime)
+       {
+               traceline(self.origin + self.view_ofs, lastcheckplayer.origin + lastcheckplayer.view_ofs, TRUE, self);
+               if (trace_fraction == 1)
+                       return lastcheckplayer;
+               if (trace_ent == lastcheckplayer)
+                       return lastcheckplayer;
+       }
+       checkplayertime = time + 0.1;
+       */
+/*
+       check = lastcheckplayer;
+       worldcount = 0;
+       c = 0;
+       do
+       {
+               c = c + 1;
+               check = findfloat(check, havocattack, TRUE);
+               if (check.classname == "player" || check.classname == "turretbase")
+               {
+                       traceline(self.origin + self.view_ofs, check.origin + check.view_ofs, TRUE, self);
+                       if (trace_fraction == 1)
+                               return lastcheckplayer = check;
+                       if (trace_ent == check)
+                               return lastcheckplayer = check;
+               }
+               else if (check == world)
+               {
+                       worldcount = worldcount + 1;
+                       if (worldcount >= 2)
+                               return lastcheckplayer = check;
+               }
+       }
+       while(check != lastcheckplayer && c < 100);
+       return world;
+}
+*/
+
+/*
+===========
+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;
+float() FindTarget =
+{
+       entity client;
+       float r;
+
+       if (self.health < 1)
+               return FALSE;
+
+       // if the first or second spawnflag bit is set, the monster will only
+       // wake up on really seeing the player, not another monster getting angry
+
+       if (self.spawnflags & 3)
+       {
+               // don't wake up on seeing another monster getting angry
+               client = checkclient ();
+               if (!client)
+                       return FALSE;   // current check entity isn't in PVS
+       }
+       else
+       {
+               if (sight_entity_time >= time)
+               {
+                       client = sight_entity;
+                       if (client.enemy == self.enemy)
+                               return TRUE;
+               }
+               else
+               {
+                       client = checkclient ();
+                       if (!client)
+                               return FALSE;   // current check entity isn't in PVS
+               }
+       }
+
+       if (client == self.enemy)
+               return FALSE;
+
+       if (client.flags & FL_NOTARGET)
+               return FALSE;
+
+#if 0
+       if (client.items & IT_INVISIBILITY)
+               return FALSE;
+#endif
+
+       // on skill 5 the monsters usually ignore the player and remain ghostlike
+       if (skill >= 5)
+       if (self.classname != "monster_hellfish")
+       if (random() < 0.99)
+               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)
+       {
+               // LordHavoc: was if ( /* client.show_hostile < time || */ !infront (client))
+               if (client.show_hostile < time && !infront (client))
+                       return FALSE;
+       }
+
+       //
+       // got one
+       //
+
+       if (client.model == "")
+               return FALSE;
+       self.enemy = client;
+       if (self.enemy.classname != "player" && self.enemy.classname != "turretbase")
+       {
+               self.enemy = self.enemy.enemy;
+               if (self.enemy.classname != "player" && self.enemy.classname != "turretbase")
+               {
+                       self.enemy = world;
+                       return FALSE;
+               }
+       }
+
+       FoundTarget ();
+
+       return TRUE;
+}
+
+
+//=============================================================================
+
+void(float dist) ai_forward =
+{
+       walkmove (self.angles_y, dist);
+}
+
+void(float dist) ai_back =
+{
+       walkmove ( (self.angles_y+180), dist);
+}
+
+
+void(float a) monster_setalpha;
+
+/*
+=============
+ai_pain
+
+stagger back a bit
+=============
+*/
+void(float dist) ai_pain =
+{
+       if (self.health < 1)
+               return;
+       ai_back (dist);
+}
+
+/*
+=============
+ai_painforward
+
+stagger back a bit
+=============
+*/
+void(float dist) ai_painforward =
+{
+       if (self.health < 1)
+               return;
+       walkmove (self.ideal_yaw, dist);
+}
+
+/*
+=============
+ai_walk
+
+The monster is walking it's beat
+=============
+*/
+void(float dist) ai_walk =
+{
+       if (self.health < 1)
+               return;
+
+       movedist = dist;
+
+       // check for noticing a player
+       if (self.oldenemy.takedamage)
+       if (self.oldenemy.health >= 1)
+       {
+               self.enemy = self.oldenemy;
+               self.oldenemy = world;
+               FoundTarget();
+               monster_setalpha(0);
+               return;
+       }
+       if (self.enemy)
+       {
+               if (self.enemy.takedamage)
+               {
+                       if (self.enemy.health >= 1)
+                       {
+                               FoundTarget();
+                               monster_setalpha(0);
+                               return;
+                       }
+                       else
+                               self.enemy = world;
+               }
+               else
+                       self.enemy = world;
+       }
+
+       self.findtarget = TRUE;
+
+       movetogoal (dist);
+       monster_setalpha(0);
+}
+
+
+/*
+=============
+ai_stand
+
+The monster is staying in one place for a while, with slight angle turns
+=============
+*/
+void() ai_stand =
+{
+       if (self.health < 1)
+               return;
+       if (self.enemy)
+       {
+               if (self.enemy.takedamage)
+               {
+                       if (self.enemy.health >= 1)
+                       {
+                               FoundTarget();
+                               monster_setalpha(0);
+                               return;
+                       }
+                       else
+                               self.enemy = world;
+               }
+               else
+                       self.enemy = world;
+       }
+       self.findtarget = TRUE;
+
+       if (time > self.pausetime)
+       {
+               self.th_walk ();
+               monster_setalpha(0);
+               return;
+       }
+
+// change angle slightly
+
+       monster_setalpha(0);
+}
+
+/*
+=============
+ai_turn
+
+don't move, but turn towards ideal_yaw
+=============
+*/
+void() ai_turn =
+{
+       if (self.enemy)
+       {
+               if (self.enemy.takedamage)
+               {
+                       if (self.enemy.health >= 1)
+                       {
+                               FoundTarget();
+                               monster_setalpha(0);
+                               return;
+                       }
+                       else
+                               self.enemy = world;
+               }
+               else
+                       self.enemy = world;
+       }
+       self.findtarget = TRUE;
+
+       ChangeYaw ();
+       monster_setalpha(0);
+}
+
+//=============================================================================
+
+/*
+=============
+ChooseTurn
+=============
+*/
+void(vector pDestvec) ChooseTurn =
+{
+       vector dir, newdir;
+
+       dir = self.origin - pDestvec;
+
+       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 =
+{
+       float delta;
+
+       delta = anglemod(self.angles_y - self.ideal_yaw);
+       if (delta > 45 && delta < 315)
+               return FALSE;
+       return TRUE;
+}
+
+
+//=============================================================================
+
+.float() th_checkattack;
+
+
+
+/*
+=============
+ai_run
+
+The monster has an enemy it is trying to kill
+=============
+*/
+void(float dist) ai_run =
+{
+       float ofs;
+       if (self.health < 1)
+               return;
+       movedist = dist;
+       // see if the enemy is dead
+       if (self.enemy.health < 1 || self.enemy.takedamage == DAMAGE_NO)
+       {
+               self.enemy = world;
+               // FIXME: look all around for other targets
+               if (self.oldenemy.health >= 1 && self.oldenemy.takedamage)
+               {
+                       self.enemy = self.oldenemy;
+                       self.oldenemy = world;
+                       HuntTarget ();
+               }
+               else
+               {
+                       if (self.movetarget)
+                               self.th_walk ();
+                       else
+                               self.th_stand ();
+                       return;
+               }
+       }
+
+       // wake up other monsters
+       self.show_hostile = time + 1;
+
+       // check knowledge of enemy
+       enemy_range = range(self.enemy);
+
+       self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
+       ChangeYaw ();
+
+       if (self.attack_state == AS_MELEE)
+       {
+               //dprint ("ai_run_melee\n");
+               //Turn and close until within an angle to launch a melee attack
+               if (FacingIdeal())
+               {
+                       self.th_melee ();
+                       self.attack_state = AS_STRAIGHT;
+               }
+               return;
+       }
+       else if (self.attack_state == AS_MISSILE)
+       {
+               //dprint ("ai_run_missile\n");
+               //Turn in place until within an angle to launch a missile attack
+               if (FacingIdeal())
+               if (self.th_missile ())
+                       self.attack_state = AS_STRAIGHT;
+               return;
+       }
+
+       if (self.th_checkattack())
+               return;                                 // beginning an attack
+
+       if (visible(self.enemy))
+               self.search_time = time + 5;
+       else if (coop)
+       {
+               // look for other coop players
+               if (self.search_time < time)
+                       self.findtarget = TRUE;
+       }
+
+       if (self.attack_state == AS_SLIDING)
+       {
+               //dprint ("ai_run_slide\n");
+               //Strafe sideways, but stay at aproximately the same range
+               if (self.lefty)
+                       ofs = 90;
+               else
+                       ofs = -90;
+
+               if (walkmove (self.ideal_yaw + ofs, movedist))
+                       return;
+
+               self.lefty = !self.lefty;
+
+               walkmove (self.ideal_yaw - ofs, movedist);
+       }
+
+       // head straight in
+       movetogoal (dist);              // done in C code...
+}
+
diff --git a/qcsrc/server/attic/monsters/defs.qc b/qcsrc/server/attic/monsters/defs.qc
new file mode 100644 (file)
index 0000000..1982142
--- /dev/null
@@ -0,0 +1,55 @@
+.entity movetarget;
+.float pausetime;
+
+.void()         th_stand;
+.void()         th_walk;
+.void()         th_run;
+.float()        th_missile; // LordHavoc: changed from void() to float(), returns true if attacking
+.void()         th_melee;
+//.void(entity attacker, float damage, float damgtype, string dethtype)           th_pain; // TODO Xonotic uses event_damage
+//.void()         th_die; // TODO never called directly by Xonotic
+.entity         oldenemy;               // mad at this player before taking damage
+entity  newmis;                 // launch_spike sets this after spawning it
+
+// range values
+float   RANGE_MELEE                             = 0;
+float   RANGE_NEAR                              = 1;
+float   RANGE_MID                               = 2;
+float   RANGE_FAR                               = 3;
+
+float DMG_KNIGHT_MELEE_BASE           =    0;
+float DMG_KNIGHT_MELEE_RANDOM1        =    3;
+float DMG_KNIGHT_MELEE_RANDOM2        =    3;
+float DMG_KNIGHT_MELEE_RANDOM3        =    3;
+
+.float          show_hostile; 
+       // set to time+0.2 whenever a client fires a
+       // weapon or takes damage.  Used to alert
+       // monsters that otherwise would let the player go
+
+float movedist;
+.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 SKILL4_MINALPHA         = 0.4;
+
+float monsterwander;
+//#NO AUTOCVARS START
+/*
+        monsterwander = cvar("monsterwander");
+        // monsterwander is always on in skill 5
+        if (skill >= 5)
+                monsterwander = TRUE;
+*/
+//#NO AUTOCVARS END
+
+.float candrown;
+
+.void(vector org, float bodydamage, float armordamage, vector vel, float damgtype) bleedfunc;
+void(vector org, float bodydamage, float armordamage, vector vel, float damgtype) genericbleedfunc;
diff --git a/qcsrc/server/attic/monsters/fight.qc b/qcsrc/server/attic/monsters/fight.qc
new file mode 100644 (file)
index 0000000..a8fcd8e
--- /dev/null
@@ -0,0 +1,252 @@
+
+/*
+
+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.
+
+*/
+
+void SUB_AttackFinished (float normal)
+{
+       self.cnt = 0;           // refire count for nightmare
+       if (skill < 3)
+               ATTACK_FINISHED(self) = time + normal;
+}
+
+float CanDamage(entity targ, entity inflictor)
+{
+       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;
+}
+
+float(float v) anglemod;
+
+void(vector dest) ChooseTurn;
+
+void() ai_face;
+
+
+float enemy_range;
+
+
+//=============================================================================
+
+/*
+===========
+GenericCheckAttack
+
+The player is in view, so decide to move or launch an attack
+Returns FALSE if movement should continue
+============
+*/
+float() GenericCheckAttack =
+{
+       vector spot1, spot2;
+       entity targ;
+       float chance;
+
+       if (self.health < 1)
+               return FALSE;
+       targ = self.enemy;
+
+       if (vlen(targ.origin - self.origin) > 5000) // long traces are slow
+               return FALSE;
+
+// see if any entities are in the way of the shot
+       spot1 = self.origin + self.view_ofs;
+       spot2 = targ.origin + targ.view_ofs;
+
+       traceline (spot1, spot2, FALSE, self);
+
+       if (trace_ent != targ)
+               return FALSE; // don't have a clear shot
+
+       if (trace_inopen && trace_inwater)
+               return FALSE; // sight line crossed contents
+
+       if (enemy_range == RANGE_MELEE)
+       {       // melee attack
+               if (self.th_melee)
+               {
+                       self.th_melee ();
+                       return TRUE;
+               }
+       }
+
+// missile attack
+       if (time < ATTACK_FINISHED(self))
+               return FALSE;
+
+       if (!self.th_missile)
+               return FALSE;
+
+       if (enemy_range == RANGE_FAR)
+               return FALSE;
+
+       if (enemy_range == RANGE_MELEE)
+       {
+               chance = 0.9;
+               ATTACK_FINISHED(self) = 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)
+       if (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
+=============
+*/
+float (entity targ) visible;
+float(entity targ) infront;
+float(entity targ) range;
+
+void(float d) ai_charge =
+{
+       if (self.health < 1)
+               return;
+       ai_face ();
+       movetogoal (d);         // done in C code...
+}
+
+void() ai_charge_side =
+{
+       if (self.health < 1)
+               return;
+       vector dtemp;
+       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 =
+{
+       vector delta;
+       float ldmg;
+
+       if (self.health < 1)
+               return;
+       if (!self.enemy)
+               return;         // removed before stroke
+
+       delta = self.enemy.origin - self.origin;
+
+       if (vlen(delta) > 60)
+               return;
+
+       ldmg = DMG_KNIGHT_MELEE_BASE + DMG_KNIGHT_MELEE_RANDOM1 * random();
+       ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM2 * random();
+       ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM3 * random();
+       traceline(self.origin, self.enemy.origin, FALSE, self);
+
+       Damage (self.enemy, self, self, ldmg, self.projectiledeathtype, trace_endpos, '0 0 0'); // TODO add force to monster melee attacks?
+}
+
+
+void() ai_melee_side =
+{
+       vector delta;
+       float ldmg;
+
+       if (self.health < 1)
+               return;
+       if (!self.enemy)
+               return;         // removed before stroke
+
+       ai_charge_side();
+
+       delta = self.enemy.origin - self.origin;
+
+       if (vlen(delta) > 60)
+               return;
+       if (!CanDamage (self.enemy, self))
+               return;
+       ldmg = DMG_KNIGHT_MELEE_BASE + DMG_KNIGHT_MELEE_RANDOM1 * random();
+       ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM2 * random();
+       ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM3 * random();
+       traceline(self.origin, self.enemy.origin, FALSE, self);
+       Damage (self.enemy, self, self, ldmg, self.projectiledeathtype, trace_endpos, '0 0 0');
+}
+
diff --git a/qcsrc/server/attic/monsters/m_monsters.qc b/qcsrc/server/attic/monsters/m_monsters.qc
new file mode 100644 (file)
index 0000000..3e160d9
--- /dev/null
@@ -0,0 +1,475 @@
+/* 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>
+// }
+
+.float ismonster;
+
+.float modelindex2;
+
+/*
+================
+monster_use
+
+Using a monster makes it angry at the current activator
+LordHavoc: using a monster with the spawnflag 'Appear' makes it appear
+================
+*/
+void() monster_use =
+{
+       if (self.enemy)
+               return;
+       if (self.health < 1)
+               return;
+       if (self.mdl)
+       if (self.spawnflags & MONSTER_APPEAR)
+       {
+               self.nextthink = time + 0.1;
+               self.spawnflags = self.spawnflags - MONSTER_APPEAR;
+               self.solid = SOLID_SLIDEBOX;
+               self.takedamage = DAMAGE_AIM;
+               //self.movetype = MOVETYPE_STEP;
+               self.model = self.mdl;
+               self.mdl = "";
+               self.modelindex = self.modelindex2;
+               self.modelindex2 = 0;
+               //setorigin(self, self.origin + '0 0 1');
+               spawn_tdeath(self.origin, self, self.origin);
+               return;
+       }
+
+#if 0
+       if (activator.items & IT_INVISIBILITY)
+               return;
+#endif
+       if (activator.flags & FL_NOTARGET)
+               return;
+       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;
+}
+
+void() monster_appearsetup =
+{
+       if ((self.spawnflags & MONSTER_APPEAR) == 0)
+               return;
+       self.mdl = self.model;
+       self.modelindex2 = self.modelindex;
+       self.modelindex = 0;
+       self.solid = SOLID_NOT;
+       self.takedamage = DAMAGE_NO;
+       //self.movetype = MOVETYPE_NONE;
+       self.nextthink = -1;
+       self.model = "";
+}
+
+/*
+================
+monster_setalpha
+
+Sets relative alpha of monster in skill 4 mode.
+================
+*/
+void(float a) monster_setalpha =
+{
+       if (skill < 4 || self.classname == "monster_hellfish")
+       {
+               self.alpha = 1.0;
+               return;
+       }
+
+       if (skill >= 5)
+       {
+               // randomly forget enemy, this makes monsters randomly return to their normal ghostlike state
+               if (a == 0)
+               if (self.enemy)
+               if (random() < 0.1)
+                       self.enemy = world;
+               // randomly blink (playing the same alarming sound as if attacking)
+               if (self.enemy == world)
+               {
+                       a = 0;
+                       if (time >= 0.3) // don't blink during the init process because it might become permanent
+                       if (random() < 0.005)
+                       {
+                               // blink for an instant, this causes the appear sound, alarming the player as if under attack
+                               /* PLEASE FIX THE SOUND CHANNEL BEFORE ACTIVATING THIS
+                               sound(self, CHAN_AUTO, "wizard/wsight.wav", 1, ATTN_NORM);
+                               */
+                               a = 1;
+                       }
+               }
+               // if ghosted, become non-solid and immune to damage
+               if (a <= 0 || self.enemy == world)
+               {
+                       self.solid = SOLID_NOT;
+                       self.takedamage = DAMAGE_NO;
+               }
+               else
+               {
+                       // if unghosting, make sure we have an enemy, otherwise stay ghosted (even if blinking) so we can't be shot while blinking
+                       /* PLEASE FIX THE SOUND CHANNEL BEFORE ACTIVATING THIS
+                       if (self.solid != SOLID_SLIDEBOX)
+                               sound(self, CHAN_AUTO, "wizard/wsight.wav", 1, ATTN_NORM);
+                       */
+                       self.solid = SOLID_SLIDEBOX;
+                       self.takedamage = DAMAGE_AIM;
+               }
+       }
+       self.alpha = SKILL4_MINALPHA + (1 - SKILL4_MINALPHA) * bound(0, a, 1);
+}
+
+/*
+================
+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;
+
+       activator = self.enemy;
+       SUB_UseTargets ();
+}
+
+
+void() monsterinwall =
+{
+       entity e;
+       if (!autocvar_developer)
+               return;
+       // this is handy for level designers,
+       // puts a spikey ball where the error is...
+       e = spawn();
+       setorigin(e, self.origin);
+       setmodel (e, "models/ebomb.mdl");
+       e.movetype = MOVETYPE_NONE;
+       e.solid = SOLID_NOT;
+       e.think = SUB_Null;
+       e.nextthink = -1;
+       e.scale = 16;
+}
+
+//============================================================================
+
+void() walkmonster_start_go =
+{
+       self.origin_z = self.origin_z + 1; // raise off floor a bit
+
+       tracebox(self.origin, self.mins, self.maxs, self.origin, TRUE, self);
+       if (trace_startsolid)
+       {
+               dprint("walkmonster in wall at: ");
+               dprint(vtos(self.origin));
+               dprint("\n");
+               monsterinwall();
+               droptofloor();
+       }
+       else
+       {
+               droptofloor();
+               if (!walkmove(0,0))
+               {
+                       dprint("walkmonster in wall at: ");
+                       dprint(vtos(self.origin));
+                       dprint("\n");
+                       monsterinwall();
+               }
+       }
+
+       //self.cantrigger = TRUE;
+
+       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 (monsterwander)
+               self.spawnflags = self.spawnflags | MONSTER_WANDER;
+
+       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
+               {
+                       if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
+                       {
+                               monster_spawnwanderpath();
+                               self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
+                               self.th_walk ();
+                       }
+                       else
+                       {
+                               self.pausetime = 99999999;
+                               self.th_stand ();
+                       }
+               }
+       }
+       else
+       {
+               if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
+               {
+                       monster_spawnwanderpath();
+                       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
+       self.nextthink = self.nextthink + random()*0.5 + 0.1;
+       self.iscreature = TRUE;
+       self.damagedbycontents = TRUE;
+
+       force_retouch = 2; // mainly to detect teleports
+
+       monster_appearsetup();
+}
+
+
+void() walkmonster_start =
+{
+       self.candrown = 1; // this is turned off by some monsters like zombies
+       // delay drop to floor to make sure all doors have been spawned
+       // spread think times so they don't all happen at same time
+       self.nextthink = time + random()*0.5 + 0.3;
+       self.think = walkmonster_start_go;
+       total_monsters = total_monsters + 1;
+       self.bot_attack = TRUE;
+       self.frags = 2; // actually just used to get havocbots to attack it...
+       self.bleedfunc = genericbleedfunc;
+       self.ismonster = TRUE;
+
+       monster_setalpha (0);
+}
+
+
+
+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");
+               monsterinwall();
+       }
+
+       //self.cantrigger = TRUE;
+
+       if (monsterwander)
+               self.spawnflags = self.spawnflags | MONSTER_WANDER;
+
+       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
+               {
+                       if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
+                       {
+                               monster_spawnwanderpath();
+                               self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
+                               self.th_walk ();
+                       }
+                       else
+                       {
+                               self.pausetime = 99999999;
+                               self.th_stand ();
+                       }
+               }
+       }
+       else
+       {
+               if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
+               {
+                       monster_spawnwanderpath();
+                       self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
+                       self.th_walk ();
+               }
+               else
+               {
+                       self.pausetime = 99999999;
+                       self.th_stand ();
+               }
+       }
+       self.iscreature = TRUE;
+       self.damagedbycontents = TRUE;
+
+       force_retouch = 2; // mainly to detect teleports
+
+       monster_appearsetup();
+}
+
+void() flymonster_start =
+{
+       self.candrown = 1;
+       // spread think times so they don't all happen at same time
+       self.nextthink = time + random()*0.5 + 0.1;
+       self.think = flymonster_start_go;
+       total_monsters = total_monsters + 1;
+       self.bot_attack = TRUE;
+       self.frags = 2; // actually just used to get havocbots to attack it...
+       self.bleedfunc = genericbleedfunc;
+       self.ismonster = TRUE;
+
+       monster_setalpha (0);
+}
+
+
+void() swimmonster_start_go =
+{
+       if (deathmatch)
+       {
+               remove(self);
+               return;
+       }
+
+       //self.cantrigger = TRUE;
+
+       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 (monsterwander)
+               self.spawnflags = self.spawnflags | MONSTER_WANDER;
+
+       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
+               {
+                       if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
+                       {
+                               monster_spawnwanderpath();
+                               self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
+                               self.th_walk ();
+                       }
+                       else
+                       {
+                               self.pausetime = 99999999;
+                               self.th_stand ();
+                       }
+               }
+       }
+       else
+       {
+               if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp"))
+               {
+                       monster_spawnwanderpath();
+                       self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
+                       self.th_walk ();
+               }
+               else
+               {
+                       self.pausetime = 99999999;
+                       self.th_stand ();
+               }
+       }
+       self.iscreature = TRUE;
+       self.damagedbycontents = TRUE;
+
+       force_retouch = 2; // mainly to detect teleports
+
+       monster_appearsetup();
+}
+
+void() swimmonster_start =
+{
+       // spread think times so they don't all happen at same time
+       self.candrown = 0;
+       self.nextthink = time + random()*0.5 + 0.1;
+       self.think = swimmonster_start_go;
+       total_monsters = total_monsters + 1;
+       self.bot_attack = TRUE;
+       self.frags = 2; // actually just used to get havocbots to attack it...
+       self.bleedfunc = genericbleedfunc;
+       self.ismonster = TRUE;
+
+       monster_setalpha(0);
+}
+
+void(vector org, float bodydamage, float armordamage, vector force, float damgtype) genericbleedfunc =
+{
+        vector v;
+        v = '0 0 0' - force * 0.05;
+        if (armordamage > 0)
+                te_spark(org, v, armordamage * 3);
+        if (bodydamage > 0)
+                te_blood(org, v, bodydamage);
+}
diff --git a/qcsrc/server/attic/monsters/monster_zombie.qc b/qcsrc/server/attic/monsters/monster_zombie.qc
new file mode 100644 (file)
index 0000000..c95c2ea
--- /dev/null
@@ -0,0 +1,575 @@
+//#define MONSTES_ENABLED
+#ifdef MONSTES_ENABLED
+
+float autocvar_g_monster_zombie_attack_run_damage;
+float autocvar_g_monster_zombie_attack_run_delay;
+float autocvar_g_monster_zombie_attack_run_force;
+float autocvar_g_monster_zombie_attack_run_hitrange;
+float autocvar_g_monster_zombie_attack_run_range;
+float autocvar_g_monster_zombie_attack_stand_damage;
+float autocvar_g_monster_zombie_attack_stand_delay;
+float autocvar_g_monster_zombie_attack_stand_force;
+float autocvar_g_monster_zombie_attack_stand_range;
+float autocvar_g_monster_zombie_health;
+float autocvar_g_monster_zombie_idle_timer_max;
+float autocvar_g_monster_zombie_idle_timer_min;
+float autocvar_g_monster_zombie_movespeed;
+float autocvar_g_monster_zombie_respawntime;
+float autocvar_g_monster_zombie_stopspeed;
+float autocvar_g_monster_zombie_targetrange;
+float autocvar_g_monster_zombie_turnspeed;
+float autocvar_g_monsters;
+
+
+#define zombie_anim_attackleap         0
+#define zombie_anim_attackrun1         1
+#define zombie_anim_attackrun2         2
+#define zombie_anim_attackrun3         3
+#define zombie_anim_attackstanding1    4
+#define zombie_anim_attackstanding2    5
+#define zombie_anim_attackstanding3    6
+#define zombie_anim_blockend           7
+#define zombie_anim_blockstart         8
+#define zombie_anim_deathback1         9
+#define zombie_anim_deathback2         10
+#define zombie_anim_deathback3         11
+#define zombie_anim_deathfront1        12
+#define zombie_anim_deathfront2        13
+#define zombie_anim_deathfront3        14
+#define zombie_anim_deathleft1         15
+#define zombie_anim_deathleft2         16
+#define zombie_anim_deathright1        17
+#define zombie_anim_deathright2        18
+#define zombie_anim_idle               19
+#define zombie_anim_painback1          20
+#define zombie_anim_painback2          21
+#define zombie_anim_painfront1         22
+#define zombie_anim_painfront2         23
+#define zombie_anim_runbackwards       24
+#define zombie_anim_runbackwardsleft   25
+#define zombie_anim_runbackwardsright  26
+#define zombie_anim_runforward         27
+#define zombie_anim_runforwardleft     28
+#define zombie_anim_runforwardright    29
+#define zombie_anim_spawn              30
+
+#define ZOMBIE_MIN                                      '-18 -18 -25'
+#define ZOMBIE_MAX                                      '18 18 47'
+
+#define ZV_IDLE     10
+
+#define ZV_PATH     100
+#define ZV_HUNT     200
+
+#define ZV_ATTACK_FIND  10
+#define ZV_ATTACK_RUN   20
+#define ZV_ATTACK_STAND 30
+
+#define ZV_PATH2 10000
+
+//.entity verbs_idle;
+//.entity verbs_attack;
+//.entity verbs_move;
+
+//.float  state_timeout;
+//.void() monster_state;
+#define MONSTERFLAG_NORESPAWN 2
+
+void zombie_spawn();
+
+float zombie_scoretarget(entity trg)
+{
+    float  tmp;
+    vector ang1;
+
+    if (trg.takedamage == DAMAGE_AIM)
+    if not (trg.flags & FL_NOTARGET)
+    if (trg.deadflag == DEAD_NO)
+    if (trg.team != self.team)
+    {
+        if((self.origin_z - trg.origin_z) < 128)
+        {
+            ang1 = normalize(self.origin - trg.origin);
+            tmp = vlen(ang1 - v_forward);
+            if(tmp > 1.5)
+            {
+                traceline(self.origin + '0 0 47',trg.origin + '0 0 32',MOVE_NORMAL,self);
+                if(trace_ent != trg)
+                    return 0;
+
+                return (autocvar_g_monster_zombie_targetrange - vlen(self.origin - trg.origin)) * tmp;
+            }
+            else if(self.enemy == trg)
+                return (autocvar_g_monster_zombie_targetrange - vlen(self.origin - trg.origin)) * tmp;
+        }
+    }
+
+    return 0;
+}
+
+void zombie_corpse_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+    //dprint("zombie_corpse_damage\n");
+    Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
+
+    self.health -= damage;
+
+    if(self.health < 0)
+    {
+        Violence_GibSplash(self, 1, 1, attacker);
+        remove(self);
+    }
+}
+
+void zombie_die(vector dir)
+{
+    vector v;
+    float f;
+
+    entity dummy;
+
+    dummy = spawn();
+    setmodel(dummy,"models/monsters/zombie.dpm");
+    setorigin(dummy, self.origin);
+    dummy.velocity  = self.velocity;
+    dummy.movetype  = MOVETYPE_BOUNCE;
+    dummy.think     = SUB_Remove;
+    dummy.nextthink = time + 3;
+    dummy.health    = 50;
+    dummy.takedamage = DAMAGE_YES;
+    dummy.event_damage = zombie_corpse_damage;
+    dummy.solid      = SOLID_CORPSE;
+    setsize(dummy,self.mins,self.maxs);
+
+    SUB_SetFade(dummy,time + 5,2);
+
+
+    v = normalize(self.origin - dir);
+    f = vlen(v_forward - v) - 1;
+    if(f > 0.5)
+        dummy.frame = zombie_anim_deathfront1 + rint(random() * 2);
+    else if(f < 0.5)
+        dummy.frame = zombie_anim_deathback1 + rint(random() * 2);
+    else
+    {
+        f = vlen(v_right - v) - 1;
+        if(f > 0.5)
+            dummy.frame = zombie_anim_deathright1 + rint(random() * 2);
+        else if(f < 0.5)
+            dummy.frame = zombie_anim_deathleft1 + rint(random() * 2);
+    }
+
+
+    if(self.spawnflags & MONSTERFLAG_NORESPAWN)
+    {
+        self.think = SUB_Remove;
+        self.nextthink = time;
+        return;
+    }
+
+    setmodel(self,"");
+    self.solid          = SOLID_NOT;
+    self.takedamage     = DAMAGE_NO;
+    self.event_damage   = SUB_Null;
+    self.enemy          = world;
+    self.think          = zombie_spawn;
+    self.nextthink      = time + autocvar_g_monster_zombie_respawntime;
+    self.pain_finished  = self.nextthink;
+}
+
+void zombie_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+
+    vector v;
+    float f;
+
+    v = normalize(self.origin - hitloc);
+    f = vlen(v_forward - v) - 1;
+
+
+    self.health -= damage;
+    self.velocity = self.velocity + force;
+    if(self.health <= 0)
+    {
+        zombie_die(hitloc);
+        return;
+    }
+
+    Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
+
+       if (damage > 50)
+               Violence_GibSplash_At(hitloc, force * -0.1, 3, 1, self, attacker);
+       if (damage > 100)
+               Violence_GibSplash_At(hitloc, force * -0.2, 3, 1, self, attacker);
+
+    if (time > self.pain_finished)
+    {
+        if(f < 0.5)
+        {
+            if(random() < 0.5)
+                self.frame = zombie_anim_painback1;
+            else
+                self.frame = zombie_anim_painback2;
+        }
+        else
+        {
+            if(random() < 0.5)
+                self.frame = zombie_anim_painfront1;
+            else
+                self.frame = zombie_anim_painfront2;
+        }
+
+        self.pain_finished = time + 0.36;
+    }
+}
+
+.vector bvec;
+.float bvec_time;
+
+void zombie_move()
+{
+    vector real_angle;
+    float vz, tdiff, tspeed;
+
+    tdiff = time - self.zoomstate;
+    tspeed = tdiff * autocvar_g_monster_zombie_turnspeed;
+    vz = self.velocity_z;
+    self.zoomstate = time;
+
+    if(self.bvec_time < time)
+    {
+        self.bvec_time = time + 0.2;
+        self.bvec = steerlib_beamsteer(steerlib_attract2(self.moveto,0.5,500,0.95),512,32,34,64);
+    }
+
+    if(self.enemy)
+        self.moveto = self.enemy.origin;
+    else
+        self.moveto = self.origin + v_forward;
+
+    self.steerto = normalize(steerlib_attract2(self.moveto,0.5,500,0.95) + self.bvec);
+
+    self.angles_y = safeangle(self.angles_y);
+    real_angle = vectoangles(self.steerto) - self.angles;
+    self.angles_y += bound(-10, real_angle_y, 10);
+
+    if(vlen(self.origin - self.moveto) > 64)
+    {
+        movelib_move_simple(v_forward ,autocvar_g_monster_zombie_movespeed,0.6);
+        if(time > self.pain_finished)
+            if(self.attack_finished_single < time)
+                self.frame = zombie_anim_runforward;
+    }
+    else
+    {
+        movelib_beak_simple(autocvar_g_monster_zombie_stopspeed);
+        if(time > self.pain_finished)
+            if(self.attack_finished_single < time)
+                self.frame = zombie_anim_idle;
+    }
+
+    self.velocity_z = vz;
+    self.steerto = self.origin;
+}
+
+float zombie_verb_idle_roam(float eval)
+{
+    switch (eval)
+    {
+    case VCM_EVAL:
+
+        if(self.enemy)
+            return VS_CALL_NO;
+
+        return verb.verb_static_value;
+
+    case VCM_DO:
+
+        self.moveto = v_forward * 128;
+        self.steerto = v_forward; //steerlib_beamsteer(v_forward,512,32,34,64);
+
+        return VS_CALL_YES_DOING;
+    }
+
+    return VS_CALL_YES_DONE;
+}
+
+float zombie_verb_idle_stand(float eval)
+{
+    switch (eval)
+    {
+    case VCM_EVAL:
+
+        if(self.enemy)
+            return VS_CALL_NO;
+
+        return verb.verb_static_value;
+
+    case VCM_DO:
+
+        self.moveto   = self.origin;
+        self.frame    = zombie_anim_idle;
+        self.velocity = '0 0 0';
+
+        return VS_CALL_YES_DOING;
+    }
+
+    return VS_CALL_YES_DONE;
+}
+
+float zombie_verb_idle(float eval)
+{
+    switch (eval)
+    {
+    case VCM_EVAL:
+
+        if(self.enemy)
+            return VS_CALL_NO;
+
+        return verb.verb_static_value;
+
+    case VCM_DO:
+        float t;
+
+        t = autocvar_g_monster_zombie_idle_timer_max -  autocvar_g_monster_zombie_idle_timer_min;
+        t = autocvar_g_monster_zombie_idle_timer_min + (random() * t);
+
+        if(random() < 0.5)
+            verbstack_push(self.verbs_idle, zombie_verb_idle_roam,  ZV_IDLE + 1, t, self);
+        else
+            verbstack_push(self.verbs_idle, zombie_verb_idle_stand, ZV_IDLE + 1, 0.1, self);
+
+        return VS_CALL_YES_DOING;
+    }
+
+    return VS_CALL_YES_DONE;
+}
+
+float zombie_verb_attack_findtarget(float eval)
+{
+    switch (eval)
+    {
+    case VCM_EVAL:
+        if(self.enemy)
+            return VS_CALL_NO;
+
+        return verb.verb_static_value;
+
+    case VCM_DO:
+
+        entity trg, best_trg;
+        float trg_score, best_trg_score;
+
+        trg = findradius(self.origin,autocvar_g_monster_zombie_targetrange);
+        while(trg)
+        {
+            trg_score = zombie_scoretarget(trg);
+            if(trg_score > best_trg_score)
+            {
+                best_trg = trg;
+                best_trg_score = trg_score;
+            }
+
+            trg = trg.chain;
+        }
+
+        if(best_trg)
+        {
+            self.enemy = best_trg;
+            dprint("Selected: ",best_trg.netname, " as target.\n");
+        }
+
+        return VS_CALL_YES_DOING;
+    }
+
+    return VS_CALL_YES_DONE;
+}
+
+void zombie_runattack_damage()
+{
+    entity oldself;
+    oldself = self;
+    self = self.owner;
+
+    if(vlen(self.origin - self.enemy.origin) > autocvar_g_monster_zombie_attack_run_hitrange)
+        return;
+
+    if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6)
+        return;
+
+    Damage(self.enemy, self, self, autocvar_g_monster_zombie_attack_run_damage, DEATH_TURRET, self.enemy.origin, normalize(self.enemy.origin - self.origin)  * autocvar_g_monster_zombie_attack_run_force);
+
+    self = oldself;
+    self.think = SUB_Remove;
+    self.nextthink = time;
+}
+
+float zombie_verb_attack_run(float eval)
+{
+    switch (eval)
+    {
+    case VCM_EVAL:
+        if not (self.enemy)
+            return VS_CALL_NO;
+
+        if(self.attack_finished_single > time)
+            return VS_CALL_NO;
+
+        if(vlen(self.origin - self.enemy.origin) > autocvar_g_monster_zombie_attack_run_range)
+            return VS_CALL_NO;
+
+        if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6)
+            return VS_CALL_NO;
+
+        return verb.verb_static_value;
+
+    case VCM_DO:
+        entity pain;
+        pain = spawn();
+        pain.owner = self;
+        pain.think = zombie_runattack_damage;
+        pain.nextthink = time + autocvar_g_monster_zombie_attack_run_delay;
+
+        self.attack_finished_single = time + 0.7;
+        self.frame = zombie_anim_attackrun1 + rint(random() * 2);
+
+        return VS_CALL_YES_DOING;
+    }
+
+    return VS_CALL_YES_DONE;
+}
+
+void zombie_standattack_damage()
+{
+    //entity oldself;
+    //oldself = self;
+    //self = self.owner;
+
+    setorigin(self,self.owner.origin + v_forward * 32);
+    RadiusDamage(self, self.owner, autocvar_g_monster_zombie_attack_stand_damage,autocvar_g_monster_zombie_attack_stand_damage,16,self, autocvar_g_monster_zombie_attack_stand_force,DEATH_TURRET,world);
+    //float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity ignore, float forceintensity, float deathtype, entity directhitentity)
+
+
+    //self = oldself;
+    self.think = SUB_Remove;
+    self.nextthink = time;
+}
+
+float zombie_verb_attack_stand(float eval)
+{
+    switch (eval)
+    {
+    case VCM_EVAL:
+        if not (self.enemy)
+            return VS_CALL_NO;
+
+        if(self.attack_finished_single > time)
+            return VS_CALL_NO;
+
+        if(vlen(self.origin - self.enemy.origin) > autocvar_g_monster_zombie_attack_stand_range)
+            return VS_CALL_NO;
+
+        if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.8)
+            return VS_CALL_NO;
+
+        return verb.verb_static_value;
+
+    case VCM_DO:
+        entity pain;
+        pain = spawn();
+        pain.owner = self;
+        pain.think = zombie_runattack_damage;
+        pain.nextthink = time + autocvar_g_monster_zombie_attack_stand_delay;
+
+        self.attack_finished_single = time + 0.7;
+        self.frame = zombie_anim_attackstanding1 + rint(random() * 1);
+        dprint("frame:",ftos(self.frame),"\n");
+
+        return VS_CALL_YES_DOING;
+    }
+
+    return VS_CALL_YES_DONE;
+}
+
+void zombie_think()
+{
+    self.angles_x *= -1;
+    makevectors(self.angles);
+    self.angles_x *= -1;
+
+    if (zombie_scoretarget(self.enemy) == 0)
+        self.enemy = world;
+
+    verbstack_pop(self.verbs_attack);
+    //verbstack_pop(self.verbs_move);
+
+    if not (self.enemy)
+        verbstack_pop(self.verbs_idle);
+
+    zombie_move();
+
+    if(self.enemy)
+        self.nextthink = time;
+    else
+        self.nextthink = time + 0.2;
+}
+
+void zombie_spawn()
+{
+    setmodel(self,"models/monsters/zombie.dpm");
+
+    self.solid          = SOLID_BBOX;
+    self.takedamage     = DAMAGE_AIM;
+    self.event_damage   = zombie_damage;
+    self.enemy          = world;
+    self.frame          = zombie_anim_spawn;
+    self.think          = zombie_think;
+    self.nextthink      = time + 2.1;
+    self.pain_finished  = self.nextthink;
+    self.movetype       = MOVETYPE_WALK;
+    self.health         = autocvar_g_monster_zombie_health;
+    self.velocity       = '0 0 0';
+    self.angles         = self.pos2;
+    self.moveto         = self.origin;
+    self.flags          = FL_MONSTER;
+
+    setorigin(self,self.pos1);
+    setsize(self,ZOMBIE_MIN,ZOMBIE_MAX);
+}
+
+
+void spawnfunc_monster_zombie()
+{
+    if not(autocvar_g_monsters)
+    {
+        remove(self);
+        return;
+    }
+
+    precache_model("models/monsters/zombie.dpm");
+
+
+    self.verbs_idle   = spawn();
+    self.verbs_attack = spawn();
+
+    self.verbs_idle.owner = self;
+    self.verbs_attack.owner = self;
+
+    self.think      = zombie_spawn;
+    self.nextthink  = time + 2;
+
+    traceline(self.origin + '0 0 10', self.origin - '0 0 32', MOVE_WORLDONLY, self);
+
+    self.pos1 = trace_endpos;
+    self.pos2 = self.angles;
+    self.team = MAX_SHOT_DISTANCE -1;
+
+    verbstack_push(self.verbs_idle, zombie_verb_idle, ZV_IDLE,0 , self);
+
+    verbstack_push(self.verbs_attack, zombie_verb_attack_findtarget, ZV_ATTACK_FIND,0 , self);
+    verbstack_push(self.verbs_attack, zombie_verb_attack_run, ZV_ATTACK_RUN,0 , self);
+    verbstack_push(self.verbs_attack, zombie_verb_attack_stand, ZV_ATTACK_STAND,0 , self);
+
+}
+
+#endif // MONSTES_ENABLED
diff --git a/qcsrc/server/attic/vehicles/bumblebee.qc b/qcsrc/server/attic/vehicles/bumblebee.qc
new file mode 100644 (file)
index 0000000..f784563
--- /dev/null
@@ -0,0 +1,371 @@
+#ifdef SVQC
+// Auto cvars
+float autocvar_g_vehicle_bumblebee_speed_forward;
+float autocvar_g_vehicle_bumblebee_speed_strafe;
+float autocvar_g_vehicle_bumblebee_speed_up;
+float autocvar_g_vehicle_bumblebee_speed_down;
+float autocvar_g_vehicle_bumblebee_turnspeed;
+float autocvar_g_vehicle_bumblebee_pitchspeed;
+float autocvar_g_vehicle_bumblebee_pitchlimit;
+float autocvar_g_vehicle_bumblebee_friction;
+
+float autocvar_g_vehicle_bumblebee_energy;
+float autocvar_g_vehicle_bumblebee_energy_regen;
+float autocvar_g_vehicle_bumblebee_energy_regen_pause;
+
+float autocvar_g_vehicle_bumblebee_health;
+float autocvar_g_vehicle_bumblebee_health_regen;
+float autocvar_g_vehicle_bumblebee_health_regen_pause;
+
+float autocvar_g_vehicle_bumblebee_shield;
+float autocvar_g_vehicle_bumblebee_shield_regen;
+float autocvar_g_vehicle_bumblebee_shield_regen_pause;
+
+float autocvar_g_vehicle_bumblebee_cannon_cost;
+float autocvar_g_vehicle_bumblebee_cannon_damage;
+float autocvar_g_vehicle_bumblebee_cannon_radius;
+float autocvar_g_vehicle_bumblebee_cannon_refire;
+float autocvar_g_vehicle_bumblebee_cannon_speed;
+float autocvar_g_vehicle_bumblebee_cannon_spread;
+float autocvar_g_vehicle_bumblebee_cannon_force;
+
+float autocvar_g_vehicle_bumblebee_cannon_turnspeed;
+float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down;
+float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up;
+float autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
+float autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
+
+float autocvar_g_vehicle_bumblebee_respawntime;
+
+float autocvar_g_vehicle_bumblebee_blowup_radius;
+float autocvar_g_vehicle_bumblebee_blowup_coredamage;
+float autocvar_g_vehicle_bumblebee_blowup_edgedamage;
+float autocvar_g_vehicle_bumblebee_blowup_forceintensity;
+
+#define BUMB_MIN '-120 -120 -40'
+#define BUMB_MAX '120 120 40'
+
+.entity gunner1;
+//.entity gunner2;
+.vector lastaim;
+float bumb_gunner_frame()
+{
+    entity vehic, gun, gunner;
+    float ftmp, ftmp2;
+    vector vtmp;
+
+    vehic   = self.vehicle;
+    gun     = self.vehicle.gun1;
+    gunner  = self;
+
+    self    = vehic;
+    vehic.solid = SOLID_NOT;
+    crosshair_trace(gunner);
+
+    //vtmp = gettaginfo(vehic, gettagindexvehic, "tag_hardpoint01"));
+    vtmp = gettaginfo(gun, gettagindex(gun, "muzzle"));
+    vtmp = vectoangles(normalize(trace_endpos - vtmp)); // Find the direction & angle
+    vtmp = shortangle_vxy(vtmp - (vehic.angles + gun.angles), vehic.angles + gun.angles);     // Find aim offset
+
+    // Bind to aimspeed
+    ftmp2 = autocvar_g_vehicle_bumblebee_cannon_turnspeed * frametime; ftmp = -ftmp2;
+    vtmp_x = bound(ftmp, vtmp_x, ftmp2);
+    vtmp_y = bound(ftmp, vtmp_y, ftmp2);
+    // Bind to limts
+    gun.angles_x = bound(-autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down, vtmp_x + gun.angles_x, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up);
+    gun.angles_y = bound(-autocvar_g_vehicle_bumblebee_cannon_turnlimit_in,  vtmp_y + gun.angles_y, autocvar_g_vehicle_bumblebee_cannon_turnlimit_out);
+
+    if(gunner.BUTTON_ATCK && gun.cnt <= time)
+    {
+        vtmp = gettaginfo(gun, gettagindex(gun, "muzzle"));
+        v_forward = normalize(v_forward);
+        vtmp += v_forward * 50;
+
+        fireBullet (vtmp, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_damage,
+            autocvar_g_vehicle_spiderbot_minigun_spread, DEATH_SBMINIGUN, 0);
+
+        gun.cnt = time + 0.1;
+    }
+
+    setorigin(gunner, vehic.origin);
+    gunner.velocity = vehic.velocity;
+
+    vehic.solid = SOLID_BBOX;
+    gunner.BUTTON_ATCK = gunner.BUTTON_ATCK2 = gunner.BUTTON_CROUCH = 0;
+    self = gunner;
+    return 1;
+}
+
+void bumb_gunner_enter()
+{
+    if(self.gunner1 != world)
+        return;
+
+    self.gunner1         = other;
+    self.gunner1.vehicle = self;
+
+    msg_entity = other;
+    WriteByte (MSG_ONE, SVC_SETVIEWPORT);
+    WriteEntity(MSG_ONE, self.gun1);
+    WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
+    if(self.tur_head)
+    {
+        WriteAngle(MSG_ONE, self.gun1.angles_x + self.angles_x); // tilt
+        WriteAngle(MSG_ONE, self.gun1.angles_y + self.angles_y); // yaw
+        WriteAngle(MSG_ONE, 0);                                  // roll
+    }
+    other.PlayerPhysplug = bumb_gunner_frame;
+}
+
+float bumb_pilot_frame()
+{
+    entity pilot, gunner, vehic;
+    vector newvel;
+
+    pilot = self;
+    vehic = self.vehicle;
+    self   = vehic;
+
+    if(pilot.BUTTON_USE && vehic.deadflag == DEAD_NO)
+    {
+        self = vehic;
+        vehicles_exit(VHEF_NORMAL);
+        self = pilot;
+        return 0;
+    }
+
+    if(vehic.deadflag != DEAD_NO)
+    {
+        self = pilot;
+        pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = 0;
+        return 1;
+    }
+
+    crosshair_trace(pilot);
+
+    vector vang;
+    float ftmp;
+
+    vang = vehic.angles;
+    newvel = vectoangles(normalize(trace_endpos - self.origin + '0 0 32'));
+    vang_x *= -1;
+    newvel_x *= -1;
+    if(newvel_x > 180)  newvel_x -= 360;
+    if(newvel_x < -180) newvel_x += 360;
+    if(newvel_y > 180)  newvel_y -= 360;
+    if(newvel_y < -180) newvel_y += 360;
+
+    ftmp = shortangle_f(pilot.v_angle_y - vang_y, vang_y);
+    if(ftmp > 180)  ftmp -= 360; if(ftmp < -180) ftmp += 360;
+    vehic.avelocity_y = bound(-autocvar_g_vehicle_bumblebee_turnspeed, ftmp + vehic.avelocity_y * 0.9, autocvar_g_vehicle_bumblebee_turnspeed);
+
+    // Pitch
+    ftmp = 0;
+    if(pilot.movement_x > 0 && vang_x < autocvar_g_vehicle_bumblebee_pitchlimit) ftmp = 5;
+    else if(pilot.movement_x < 0 && vang_x > -autocvar_g_vehicle_bumblebee_pitchlimit) ftmp = -20;
+
+    newvel_x = bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel_x , autocvar_g_vehicle_bumblebee_pitchlimit);
+    ftmp = vang_x - bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel_x + ftmp, autocvar_g_vehicle_bumblebee_pitchlimit);
+    vehic.avelocity_x = bound(-autocvar_g_vehicle_bumblebee_pitchspeed, ftmp + vehic.avelocity_x * 0.9, autocvar_g_vehicle_bumblebee_pitchspeed);
+
+    vehic.angles_x = anglemods(vehic.angles_x);
+    vehic.angles_y = anglemods(vehic.angles_y);
+    vehic.angles_z = anglemods(vehic.angles_z);
+
+    makevectors('0 1 0' * vehic.angles_y);
+    newvel = vehic.velocity * -autocvar_g_vehicle_bumblebee_friction;
+
+    if(pilot.movement_x != 0)
+    {
+        if(pilot.movement_x > 0)
+            newvel += v_forward  * autocvar_g_vehicle_bumblebee_speed_forward;
+        else if(pilot.movement_x < 0)
+            newvel -= v_forward  * autocvar_g_vehicle_bumblebee_speed_forward;
+    }
+
+    if(pilot.movement_y != 0)
+    {
+        if(pilot.movement_y < 0)
+            newvel -= v_right * autocvar_g_vehicle_bumblebee_speed_strafe;
+        else if(pilot.movement_y > 0)
+            newvel += v_right * autocvar_g_vehicle_bumblebee_speed_strafe;
+        ftmp = newvel * v_right;
+        ftmp *= frametime * 0.1;
+        vehic.angles_z = bound(-15, vehic.angles_z + ftmp, 15);
+    }
+    else
+    {
+        vehic.angles_z *= 0.95;
+        if(vehic.angles_z >= -1 && vehic.angles_z <= -1)
+            vehic.angles_z = 0;
+    }
+
+    if(pilot.BUTTON_CROUCH)
+        newvel -=   v_up * autocvar_g_vehicle_bumblebee_speed_down;
+    else if (pilot.BUTTON_JUMP)
+        newvel +=  v_up * autocvar_g_vehicle_bumblebee_speed_up;
+
+    vehic.velocity  += newvel * frametime;
+    pilot.velocity = pilot.movement  = vehic.velocity;
+    setorigin(pilot,vehic.origin + '0 0 32');
+
+
+    if(vehic.vehicle_flags  & VHF_SHIELDREGEN)
+        vehicles_regen(dmg_time, vehicle_shield, autocvar_g_vehicle_bumblebee_shield, autocvar_g_vehicle_bumblebee_shield_regen_pause, autocvar_g_vehicle_bumblebee_shield_regen, frametime);
+
+    if(vehic.vehicle_flags  & VHF_HEALTHREGEN)
+        vehicles_regen(dmg_time, vehicle_health, autocvar_g_vehicle_bumblebee_health, autocvar_g_vehicle_bumblebee_health_regen_pause, autocvar_g_vehicle_bumblebee_health_regen, frametime);
+
+    if(vehic.vehicle_flags  & VHF_ENERGYREGEN)
+        vehicles_regen(cnt, vehicle_energy, autocvar_g_vehicle_bumblebee_energy, autocvar_g_vehicle_bumblebee_energy_regen_pause, autocvar_g_vehicle_bumblebee_energy_regen, frametime);
+
+    VEHICLE_UPDATE_PLAYER(health, bumblebee);
+    VEHICLE_UPDATE_PLAYER(energy, bumblebee);
+    if(vehic.vehicle_flags & VHF_HASSHIELD)
+        VEHICLE_UPDATE_PLAYER(shield, bumblebee);
+
+    pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = pilot.BUTTON_CROUCH = 0;
+    self = pilot;
+
+    return 1;
+}
+
+void bumb_think()
+{
+    self.velocity = self.velocity * 0.99;
+    self.nextthink = time + 0.1;
+}
+
+void bumb_enter()
+{
+    self.touch  = bumb_gunner_enter;
+}
+
+void bumb_exit(float eject)
+{
+    self.owner = world;
+    self.touch = vehicles_touch;
+}
+
+void bumb_spawn()
+{
+    self.vehicle_health = autocvar_g_vehicle_bumblebee_health;
+    self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
+    self.movetype       = MOVETYPE_TOSS;
+    self.solid          = SOLID_BBOX;
+    //self.vehicle_energy = 1;
+    self.movetype = MOVETYPE_FLY;
+    setorigin(self, self.origin + '0 0 25');
+}
+
+void bumb_die()
+{
+    self.health       = 0;
+    self.event_damage = SUB_Null;
+    self.solid        = SOLID_CORPSE;
+    self.takedamage   = DAMAGE_NO;
+    self.deadflag     = DEAD_DYING;
+    self.movetype     = MOVETYPE_BOUNCE;
+
+    pointparticles(particleeffectnum("rocket_explode"), findbetterlocation (self.origin, 16), '0 0 0', 1);
+}
+
+void bumb_dinit()
+{
+    if not (vehicle_initialize(
+             "Bumblebee",
+             "models/vehicles/bumblebee_body.dpm",
+             "",
+             "models/vehicles/spiderbot_cockpit.dpm",
+             "", "", "tag_viewport",
+             HUD_BUMBLEBEE,
+             BUMB_MIN, BUMB_MAX,
+             FALSE,
+             bumb_spawn, autocvar_g_vehicle_bumblebee_respawntime,
+             bumb_pilot_frame,
+             bumb_enter, bumb_exit,
+             bumb_die,   bumb_think,
+             FALSE))
+    {
+        remove(self);
+        return;
+    }
+    self.gun1 = spawn();
+    setmodel(self.gun1, "models/vehicles/bumblebee_ray.dpm");
+    setattachment(self.gun1, self, "tag_hardpoint03");
+
+    self.gun1 = spawn();
+    self.gun2 = spawn();
+
+    self.gun1.owner = self;
+    self.gun2.owner = self;
+
+    setmodel(self.gun1, "models/vehicles/bumblebee_plasma_right.dpm");
+    setmodel(self.gun2, "models/vehicles/bumblebee_plasma_left.dpm");
+
+    setattachment(self.gun1, self, "tag_hardpoint01");
+    setattachment(self.gun2, self, "tag_hardpoint02");
+
+    vector ofs;
+    ofs = gettaginfo(self, gettagindex(self, "tag_hardpoint01"));
+    ofs -= self.origin;
+    setattachment(self.gun1, self, "");
+    setorigin(self.gun1, ofs);
+
+    ofs = gettaginfo(self, gettagindex(self, "tag_hardpoint02"));
+    ofs -= self.origin;
+    setattachment(self.gun2, self, "");
+    setorigin(self.gun2, ofs);
+
+
+}
+
+void spawnfunc_vehicle_bumblebee()
+{
+
+    precache_model ("models/vehicles/bumblebee_body.dpm");
+    precache_model ("models/vehicles/bumblebee_plasma_left.dpm");
+    precache_model ("models/vehicles/bumblebee_plasma_right.dpm");
+    precache_model ("models/vehicles/bumblebee_ray.dpm");
+
+    //vehicles_configcheck("vehicle_bumblebee.cfg", autocvar_g_vehicle_bumblebee_health);
+
+    if(autocvar_g_vehicle_bumblebee_energy)
+        if(autocvar_g_vehicle_bumblebee_energy_regen)
+            self.vehicle_flags |= VHF_ENERGYREGEN;
+
+    if(autocvar_g_vehicle_bumblebee_shield)
+        self.vehicle_flags |= VHF_HASSHIELD;
+
+    if(autocvar_g_vehicle_bumblebee_shield_regen)
+        self.vehicle_flags |= VHF_SHIELDREGEN;
+
+    if(autocvar_g_vehicle_bumblebee_health_regen)
+        self.vehicle_flags |= VHF_HEALTHREGEN;
+
+    self.think = bumb_dinit;
+    self.nextthink = time + 1;
+}
+#endif // SVQC
+
+#ifdef CSQC
+void bumblebee_draw()
+{
+
+}
+
+void bumblebee_draw2d()
+{
+
+}
+
+void bumblebee_read_extra()
+{
+
+}
+
+void vehicle_bumblebee_assemble()
+{
+
+}
+#endif //CSQC
diff --git a/qcsrc/server/attic/vehicles/collision.qc b/qcsrc/server/attic/vehicles/collision.qc
new file mode 100644 (file)
index 0000000..11488a0
--- /dev/null
@@ -0,0 +1,55 @@
+vector collision_force;
+vector collision_angle;
+
+vector bb1[9];
+vector bb2[9];
+
+float collision_run()
+{
+    vector vtmp, vmin, vmax, vrot, vforce, vtmp2, vtmp3;
+    float i, fvel, bcol;
+
+
+    // Extract the 8 bbox corners from mins/maxs for self
+    vmax = self.maxs;
+    vmin = self.mins;
+    bb1[0] = vmax;
+    vtmp   = vmax; vtmp_x = vmin_x; bb1[1] = vtmp;
+    vtmp   = vmax; vtmp_y = vmin_y; bb1[2] = vtmp;
+    vtmp   = vmin; vtmp_z = vmax_z; bb1[3] = vtmp;
+    bb1[4] = vmin;
+    vtmp   = vmin; vtmp_x = vmax_x; bb1[5] = vtmp;
+    vtmp   = vmin; vtmp_y = vmax_y; bb1[6] = vtmp;
+    vtmp   = vmax; vtmp_z = vmin_z; bb1[7] = vtmp;
+
+    makevectors(self.angles + '-2 0 0' * self.angles_x);
+    bcol = 0;
+
+    // Pass1: Transform by rotation, ajust points by impact/s
+    for(i = 8; i >= 0; --i)
+    {
+        vtmp = bb1[i];
+        vtmp = self.origin + vtmp_x * v_forward - vtmp_y * v_right + vtmp_z * v_up;
+        traceline(self.origin, vtmp, MOVE_WORLDONLY, self);
+        te_lightning1(world,self.origin,vtmp);
+        if(trace_fraction != 1.0)
+        {
+            vforce += (trace_endpos - vtmp);
+            vtmp3 = self.origin + self.velocity * frametime;
+            vtmp2 =  vectoangles(normalize(vtmp - vtmp3));
+            vrot   += (vectoangles(normalize(trace_endpos - vtmp3)) - vtmp2);
+            bcol += 1;
+        }
+    }
+
+    if(bcol)
+    {
+
+        vtmp = self.origin + self.velocity * frametime;
+        self.angles += vrot * frametime;
+        self.velocity += vforce * frametime;
+
+    }
+
+}
+
diff --git a/qcsrc/server/attic/vehicles/network.qc b/qcsrc/server/attic/vehicles/network.qc
new file mode 100644 (file)
index 0000000..688aa7c
--- /dev/null
@@ -0,0 +1,237 @@
+#ifdef VEHICLES_CSQC
+// SendFlags
+float VSF_SETUP       = 1;          /// Send vehicle type etc
+float VSF_ORIGIN      = 2;          /// Send location
+float VSF_MOVEMENT    = 4;          /// Send movement update (and angles)
+float VSF_AVEL        = 8;          /// Send Angular velocity
+float VSF_STATS       = 16;         /// Send ammo, health etc
+float VSF_EXTRA       = 32;         /// Send additional data (turret rotations etc). Handeld per vehicle type.
+float VSF_ANIMINFO    = 64;         /// Animation info
+float VSF_FULL_UPDATE = 16777215;    /// Send everything
+
+float VSX_FAR   = 1;
+float VSX_OWNER = 2;
+float VSX_GUN1  = 4;
+float VSX_GUN2  = 8;
+
+#ifdef SVQC
+#define VSX_FARDISTANCE 2000
+float send_vehile(entity to, float sf)
+{
+       float dist, xf;
+
+    var void WriteFunc(float, float);
+
+    dist = vlen(self.origin - to.origin);
+    if(to == self.owner)
+        xf |= VSX_OWNER;
+    else if(dist > VSX_FARDISTANCE)
+        xf |= VSX_FAR;
+
+       // Always send a movement and origin to owner
+       if(to == self.owner)
+           sf |= VSF_ORIGIN | VSF_MOVEMENT;
+
+       WriteByte(MSG_ENTITY, ENT_CLIENT_VEHICLE);
+
+       // We need to know client-side what was sent
+       WriteByte(MSG_ENTITY, sf);
+       WriteByte(MSG_ENTITY, xf);
+
+       if(sf & VSF_SETUP)
+       {
+        WriteByte(MSG_ENTITY,  self.hud);        //vehicle type = hud
+        WriteByte(MSG_ENTITY,  self.team);
+        WriteShort(MSG_ENTITY, self.colormap);
+        WriteShort(MSG_ENTITY, self.vehicle_flags);
+       }
+
+    if(sf & VSF_ORIGIN)
+    {
+        WriteFunc = ((xf & VSX_FAR) ? WriteShort : WriteCoord);
+        WriteFunc(MSG_ENTITY, self.origin_x);
+        WriteFunc(MSG_ENTITY, self.origin_y);
+        WriteFunc(MSG_ENTITY, self.origin_z);
+    }
+
+    if(sf & VSF_MOVEMENT)
+    {
+        WriteFunc = ((xf & VSX_FAR) ? WriteShort : WriteCoord);
+        WriteFunc(MSG_ENTITY, self.velocity_x);
+        WriteFunc(MSG_ENTITY, self.velocity_y);
+        WriteFunc(MSG_ENTITY, self.velocity_z);
+
+        WriteFunc = ((xf & VSX_FAR) ? WriteShort : WriteAngle);
+        WriteFunc(MSG_ENTITY, self.angles_x);
+        WriteFunc(MSG_ENTITY, self.angles_y);
+        WriteFunc(MSG_ENTITY, self.angles_z);
+    }
+
+    if(sf & VSF_AVEL)
+    {
+        WriteFunc = ((xf & VSX_FAR) ? WriteShort : WriteCoord);
+        WriteFunc(MSG_ENTITY, self.avelocity_x);
+        WriteFunc(MSG_ENTITY, self.avelocity_y);
+        WriteFunc(MSG_ENTITY, self.avelocity_z);
+    }
+
+    if(sf & VSF_STATS)
+    {
+        WriteByte(MSG_ENTITY, self.vehicle_health);
+        if(xf & VSX_OWNER)
+        {
+            WriteByte(MSG_ENTITY, self.vehicle_shield);
+            WriteByte(MSG_ENTITY, self.vehicle_energy);
+
+            WriteByte(MSG_ENTITY, self.vehicle_ammo1);
+            WriteByte(MSG_ENTITY, self.vehicle_reload1);
+
+            WriteByte(MSG_ENTITY, self.vehicle_ammo2);
+            WriteByte(MSG_ENTITY, self.vehicle_reload2);
+
+        }
+    }
+
+    if(sf & VSF_EXTRA)
+        self.vehile_send_exta(to, sf);
+
+    return TRUE;
+}
+
+void net_link_vehile()
+{
+    self.SendFlags = 0xFFFFFF;
+    Net_LinkEntity(self, FALSE, 0, send_vehile);
+}
+#endif // SVQC
+
+#ifdef CSQC
+void vehicle_spiderbot_assemble()
+{
+
+}
+
+void vehicle_raptor_assemble()
+{
+
+}
+
+void vehicle_bumblebee_assemble()
+{
+
+}
+
+.float lastupdate;
+void read_vehicle(float bIsNew)
+{
+    float sf, xf;
+    var float ReadFunc();
+
+    sf = ReadByte();
+    xf = ReadByte();
+
+    if(xf & VSX_OWNER)
+        vehicle = self;
+
+       if(sf & VSF_SETUP)
+       {
+        self.vehicle_hud   = ReadByte();
+        self.team          = ReadByte();
+        self.colormap      = ReadShort();
+        self.vehicle_flags = ReadShort();
+
+        switch(self.vehicle_hud)
+        {
+            case HUD_WAKIZASHI:
+                vehicle_racer_assemble();
+                break;
+            case HUD_SPIDERBOT:
+                vehicle_spiderbot_assemble();
+                break;
+            case HUD_RAPTOR:
+                vehicle_raptor_assemble();
+                break;
+            case HUD_BUMBLEBEE:
+                vehicle_bumblebee_assemble();
+                break;
+            default:
+                break;
+        }
+       }
+
+       if(self.vehicle_hud == HUD_WAKIZASHI && xf & VSX_OWNER)
+       {
+
+        vehicle_hudmodel.owner  = self;
+       }
+
+    //if(xf & VSX_FAR)
+    //    dprint("Client vehicle faaar set\n");
+
+    if(sf & VSF_ORIGIN)
+    {
+        ReadFunc = ((xf & VSX_FAR) ? ReadShort : ReadCoord);
+        self.origin_x = ReadFunc();
+        self.origin_y = ReadFunc();
+        self.origin_z = ReadFunc();
+
+        setorigin(self, self.origin);
+        //self.lastupdate = time;
+    }
+
+    if(sf & VSF_MOVEMENT)
+    {
+        ReadFunc = ((xf & VSX_FAR) ? ReadShort : ReadCoord);
+        self.velocity_x  = ReadFunc();
+        self.velocity_y  = ReadFunc();
+        self.velocity_z  = ReadFunc();
+
+        ReadFunc = ((sf & VSX_FAR) ? ReadShort : ReadAngle);
+        self.angles_x = ReadFunc();
+        self.angles_y = ReadFunc();
+        self.angles_z = ReadFunc();
+
+        //self.lastupdate = time;
+        // self.move_velocity  = self.velocity;
+        // self.move_angles    = self.angles;
+    }
+
+    if(sf & VSF_AVEL)
+    {
+        ReadFunc = ((xf & VSX_FAR) ? ReadShort : ReadCoord);
+        self.avelocity_x = ReadFunc();
+        self.avelocity_y = ReadFunc();
+        self.avelocity_z = ReadFunc();
+
+        // self.move_avelocity  = self.avelocity;
+    }
+
+    if(sf & VSF_STATS)
+    {
+        self.vehicle_health = ReadByte();
+        if(xf & VSX_OWNER)
+        {
+            self.vehicle_shield  = ReadByte();
+            self.vehicle_energy  = ReadByte();
+            self.vehicle_ammo1   = ReadByte();
+            self.vehicle_reload1 = ReadByte();
+            self.vehicle_ammo2   = ReadByte();
+            self.vehicle_reload2 = ReadByte();
+        }
+    }
+
+    if(sf & VSF_EXTRA)
+        self.vehile_read_exta(sf);
+
+}
+
+#endif // CSQC
+#else
+#ifdef CSQC
+.float lastupdate;
+void read_vehicle(float bIsNew)
+{
+
+}
+#endif
+#endif // VEHICLES_CSQC
diff --git a/qcsrc/server/attic/verbstack.qc b/qcsrc/server/attic/verbstack.qc
new file mode 100644 (file)
index 0000000..b0601af
--- /dev/null
@@ -0,0 +1,274 @@
+/// Some default stacks.
+.entity verbs_idle;
+.entity verbs_attack;
+.entity verbs_move;
+//.entity vchain;
+
+/// This global gets set to the verb in question each time the stack manager calls verb_call
+entity verb;
+//.entity current_verb;
+//.float verb_done;
+
+/// Execure this verb
+#define VCM_DO     0
+/// Return the value of this verb. Return VS_CALL_REMOVE to delete it.
+#define VCM_EVAL   1
+/// This verb is beeing removed NOW (not sent when verb_call returns VS_CALL_REMOVE)
+#define VCM_REMOVE 2
+
+/// Verb callback
+.float(float message) verb_call;
+
+/// Points to this verb's stack.
+.entity  verbstack;
+
+/// Static value of this verb
+.float verb_static_value;
+
+/// verb_call returns this when a verb in not doable
+#define VS_CALL_NO        0
+/// verb_call(VCM_DO) returns this when a verb is executing
+#define VS_CALL_YES_DOING -1
+/// verb_call(VCM_DO) returns this when a verb did execure and is done
+#define VS_CALL_YES_DONE  -2
+/// verb_call(VCM_DO) returns this when a verb should be deleted by the stack manager
+#define VS_CALL_REMOVE    -3
+
+/*
+void verbstack_updatechain(entity stack)
+{
+    entity vrb, v;
+    if not (stack)
+        return;
+
+    dprint("verbstack_updatechain\n");
+
+    vrb = findchainentity(verbstack, stack);
+    if not (vrb)
+    {
+        stack.vchain = world;
+        return;
+    }
+
+    stack.vchain = vrb;
+    v = vrb;
+
+    while(vrb)
+    {
+        vrb = vrb.chain;
+
+
+    }
+}
+
+void verbstack_remove(entity vverb)
+{
+    entity vstack;
+    dprint("verbstack_remove\n");
+
+    vstack = verb.verbstack;
+    remove(vverb);
+    vverb.verbstack = world;
+    verbstack_updatechain(vstack);
+
+    //vverb.think = SUB_Remove;
+    //vverb.nextthink = time;
+}
+
+void verbstack_thinkremove()
+{
+    dprint("verbstack_thinkremove\n");
+    verbstack_remove(self);
+}
+*/
+
+/**
+    Push a new verb onto the specified stack. Set vrb_life to make it time-limited.
+**/
+entity verbstack_push(entity stack, float(float eval) vrb_call, float val_static, float vrb_life,entity verb_owner)
+{
+    entity vrb;
+
+    if not(stack)
+        return world;
+
+    if not(vrb_call)
+        return world;
+
+    vrb                   = spawn();
+    vrb.owner             = verb_owner;
+    vrb.verbstack         = stack;
+    vrb.verb_call         = vrb_call;
+    vrb.verb_static_value = val_static;
+
+    vrb.classname         = "verb";
+    stack.classname       = "verbstack";
+
+    if(vrb_life)
+    {
+        //vrb.think     = verbstack_thinkremove;
+        vrb.think     = SUB_Remove;
+        vrb.nextthink = time + vrb_life;
+    }
+
+    //verbstack_updatechain(stack);
+
+    return vrb;
+}
+
+/**
+    Find the best verb in this stack and execurte it.
+    ALso remove any verbs returning VS_CALL_REMOVE on VCM_EVAL or VCM_DO
+**/
+float verbstack_pop(entity stack)
+{
+    entity vrb, bestverb, oldself;
+    float  value, bestvalue;
+
+    oldself = self;
+
+    vrb = findchainentity(verbstack,stack);
+    //vrb = stack.vchain;
+    //dprint("owner:", stack.owner.classname, " vsn:", stack.classname,"\n");
+    while(vrb)
+    {
+        //dprint("vn:", vrb.classname,"\n");
+        verb  = vrb;
+        vrb   = vrb.chain;
+        self  = verb.owner;
+        value = verb.verb_call(VCM_EVAL);
+
+        if(value < 0)
+        {
+            if(value == VS_CALL_REMOVE)
+                remove(verb);
+        }
+        else
+        {
+            if(value > bestvalue)
+            {
+                bestverb  = verb;
+                bestvalue = value;
+            }
+        }
+    }
+
+    if(bestverb)
+    {
+        verb  = bestverb;
+        self  = verb.owner;
+        value = verb.verb_call(VCM_DO);
+
+        if(value == VS_CALL_REMOVE)
+            remove(bestverb);
+    }
+
+    self = oldself;
+
+    return value;
+}
+
+float verbstack_popfifo(entity stack)
+{
+    entity oldself;
+    float ret;
+
+    oldself = self;
+    verb = findentity(stack,verbstack,stack);
+    if not (verb)
+        ret = 0;
+    else
+    {
+        self = verb.owner;
+        ret = verb.verb_call(VCM_DO);
+
+        if(ret == VS_CALL_REMOVE)
+            remove(verb);
+    }
+
+    self = oldself;
+    return ret;
+}
+
+/**
+    Find the best verb in this stack and return it.
+    ALso remove any verbs returning VS_CALL_REMOVE on VCM_EVAL.
+**/
+entity verbstack_pull(entity stack)
+{
+    entity vrb;
+    entity bestverb, oldself;
+    float  value, bestvalue;
+
+    oldself = self;
+
+    vrb = findchainentity(verbstack,stack);
+    while(vrb)
+    {
+        self = vrb.owner;
+
+        verb  = vrb;
+        vrb   = vrb.chain;
+        value = verb.verb_call(VCM_EVAL);
+
+        if(value < 0)
+        {
+            if(value == VS_CALL_REMOVE)
+                remove(verb);
+        }
+        else
+        {
+            if(value > bestvalue)
+            {
+                bestverb = verb;
+                bestvalue = value;
+            }
+        }
+    }
+
+    self = oldself;
+
+    return bestverb;
+}
+
+entity verbstack_pullfifo(entity stack)
+{
+    return findentity(stack,verbstack,stack);
+}
+
+/**
+    Delete every verb on this stack, signaling them with VCM_REMOVE first.
+**/
+void verbstack_flush(entity stack)
+{
+    entity vrb, oldself;
+
+    oldself = self;
+
+    vrb = findchainentity(verbstack,stack);
+    while(vrb)
+    {
+        self = vrb.owner;
+
+        verb = vrb;
+        vrb  = vrb.chain;
+        verb.verb_call(VCM_REMOVE);
+        remove(verb);
+    }
+
+    self = oldself;
+
+    //stack.vchain = world;
+}
+
+void verbstack_doverb(entity vrb)
+{
+    float value;
+
+    verb  = vrb;
+    self  = verb.owner;
+    value = verb.verb_call(VCM_DO);
+
+    if(value == VS_CALL_REMOVE)
+        remove(vrb);
+}
diff --git a/qcsrc/server/vehicles/bumblebee.qc b/qcsrc/server/vehicles/bumblebee.qc
deleted file mode 100644 (file)
index f784563..0000000
+++ /dev/null
@@ -1,371 +0,0 @@
-#ifdef SVQC
-// Auto cvars
-float autocvar_g_vehicle_bumblebee_speed_forward;
-float autocvar_g_vehicle_bumblebee_speed_strafe;
-float autocvar_g_vehicle_bumblebee_speed_up;
-float autocvar_g_vehicle_bumblebee_speed_down;
-float autocvar_g_vehicle_bumblebee_turnspeed;
-float autocvar_g_vehicle_bumblebee_pitchspeed;
-float autocvar_g_vehicle_bumblebee_pitchlimit;
-float autocvar_g_vehicle_bumblebee_friction;
-
-float autocvar_g_vehicle_bumblebee_energy;
-float autocvar_g_vehicle_bumblebee_energy_regen;
-float autocvar_g_vehicle_bumblebee_energy_regen_pause;
-
-float autocvar_g_vehicle_bumblebee_health;
-float autocvar_g_vehicle_bumblebee_health_regen;
-float autocvar_g_vehicle_bumblebee_health_regen_pause;
-
-float autocvar_g_vehicle_bumblebee_shield;
-float autocvar_g_vehicle_bumblebee_shield_regen;
-float autocvar_g_vehicle_bumblebee_shield_regen_pause;
-
-float autocvar_g_vehicle_bumblebee_cannon_cost;
-float autocvar_g_vehicle_bumblebee_cannon_damage;
-float autocvar_g_vehicle_bumblebee_cannon_radius;
-float autocvar_g_vehicle_bumblebee_cannon_refire;
-float autocvar_g_vehicle_bumblebee_cannon_speed;
-float autocvar_g_vehicle_bumblebee_cannon_spread;
-float autocvar_g_vehicle_bumblebee_cannon_force;
-
-float autocvar_g_vehicle_bumblebee_cannon_turnspeed;
-float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down;
-float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up;
-float autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
-float autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
-
-float autocvar_g_vehicle_bumblebee_respawntime;
-
-float autocvar_g_vehicle_bumblebee_blowup_radius;
-float autocvar_g_vehicle_bumblebee_blowup_coredamage;
-float autocvar_g_vehicle_bumblebee_blowup_edgedamage;
-float autocvar_g_vehicle_bumblebee_blowup_forceintensity;
-
-#define BUMB_MIN '-120 -120 -40'
-#define BUMB_MAX '120 120 40'
-
-.entity gunner1;
-//.entity gunner2;
-.vector lastaim;
-float bumb_gunner_frame()
-{
-    entity vehic, gun, gunner;
-    float ftmp, ftmp2;
-    vector vtmp;
-
-    vehic   = self.vehicle;
-    gun     = self.vehicle.gun1;
-    gunner  = self;
-
-    self    = vehic;
-    vehic.solid = SOLID_NOT;
-    crosshair_trace(gunner);
-
-    //vtmp = gettaginfo(vehic, gettagindexvehic, "tag_hardpoint01"));
-    vtmp = gettaginfo(gun, gettagindex(gun, "muzzle"));
-    vtmp = vectoangles(normalize(trace_endpos - vtmp)); // Find the direction & angle
-    vtmp = shortangle_vxy(vtmp - (vehic.angles + gun.angles), vehic.angles + gun.angles);     // Find aim offset
-
-    // Bind to aimspeed
-    ftmp2 = autocvar_g_vehicle_bumblebee_cannon_turnspeed * frametime; ftmp = -ftmp2;
-    vtmp_x = bound(ftmp, vtmp_x, ftmp2);
-    vtmp_y = bound(ftmp, vtmp_y, ftmp2);
-    // Bind to limts
-    gun.angles_x = bound(-autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down, vtmp_x + gun.angles_x, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up);
-    gun.angles_y = bound(-autocvar_g_vehicle_bumblebee_cannon_turnlimit_in,  vtmp_y + gun.angles_y, autocvar_g_vehicle_bumblebee_cannon_turnlimit_out);
-
-    if(gunner.BUTTON_ATCK && gun.cnt <= time)
-    {
-        vtmp = gettaginfo(gun, gettagindex(gun, "muzzle"));
-        v_forward = normalize(v_forward);
-        vtmp += v_forward * 50;
-
-        fireBullet (vtmp, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_damage,
-            autocvar_g_vehicle_spiderbot_minigun_spread, DEATH_SBMINIGUN, 0);
-
-        gun.cnt = time + 0.1;
-    }
-
-    setorigin(gunner, vehic.origin);
-    gunner.velocity = vehic.velocity;
-
-    vehic.solid = SOLID_BBOX;
-    gunner.BUTTON_ATCK = gunner.BUTTON_ATCK2 = gunner.BUTTON_CROUCH = 0;
-    self = gunner;
-    return 1;
-}
-
-void bumb_gunner_enter()
-{
-    if(self.gunner1 != world)
-        return;
-
-    self.gunner1         = other;
-    self.gunner1.vehicle = self;
-
-    msg_entity = other;
-    WriteByte (MSG_ONE, SVC_SETVIEWPORT);
-    WriteEntity(MSG_ONE, self.gun1);
-    WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
-    if(self.tur_head)
-    {
-        WriteAngle(MSG_ONE, self.gun1.angles_x + self.angles_x); // tilt
-        WriteAngle(MSG_ONE, self.gun1.angles_y + self.angles_y); // yaw
-        WriteAngle(MSG_ONE, 0);                                  // roll
-    }
-    other.PlayerPhysplug = bumb_gunner_frame;
-}
-
-float bumb_pilot_frame()
-{
-    entity pilot, gunner, vehic;
-    vector newvel;
-
-    pilot = self;
-    vehic = self.vehicle;
-    self   = vehic;
-
-    if(pilot.BUTTON_USE && vehic.deadflag == DEAD_NO)
-    {
-        self = vehic;
-        vehicles_exit(VHEF_NORMAL);
-        self = pilot;
-        return 0;
-    }
-
-    if(vehic.deadflag != DEAD_NO)
-    {
-        self = pilot;
-        pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = 0;
-        return 1;
-    }
-
-    crosshair_trace(pilot);
-
-    vector vang;
-    float ftmp;
-
-    vang = vehic.angles;
-    newvel = vectoangles(normalize(trace_endpos - self.origin + '0 0 32'));
-    vang_x *= -1;
-    newvel_x *= -1;
-    if(newvel_x > 180)  newvel_x -= 360;
-    if(newvel_x < -180) newvel_x += 360;
-    if(newvel_y > 180)  newvel_y -= 360;
-    if(newvel_y < -180) newvel_y += 360;
-
-    ftmp = shortangle_f(pilot.v_angle_y - vang_y, vang_y);
-    if(ftmp > 180)  ftmp -= 360; if(ftmp < -180) ftmp += 360;
-    vehic.avelocity_y = bound(-autocvar_g_vehicle_bumblebee_turnspeed, ftmp + vehic.avelocity_y * 0.9, autocvar_g_vehicle_bumblebee_turnspeed);
-
-    // Pitch
-    ftmp = 0;
-    if(pilot.movement_x > 0 && vang_x < autocvar_g_vehicle_bumblebee_pitchlimit) ftmp = 5;
-    else if(pilot.movement_x < 0 && vang_x > -autocvar_g_vehicle_bumblebee_pitchlimit) ftmp = -20;
-
-    newvel_x = bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel_x , autocvar_g_vehicle_bumblebee_pitchlimit);
-    ftmp = vang_x - bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel_x + ftmp, autocvar_g_vehicle_bumblebee_pitchlimit);
-    vehic.avelocity_x = bound(-autocvar_g_vehicle_bumblebee_pitchspeed, ftmp + vehic.avelocity_x * 0.9, autocvar_g_vehicle_bumblebee_pitchspeed);
-
-    vehic.angles_x = anglemods(vehic.angles_x);
-    vehic.angles_y = anglemods(vehic.angles_y);
-    vehic.angles_z = anglemods(vehic.angles_z);
-
-    makevectors('0 1 0' * vehic.angles_y);
-    newvel = vehic.velocity * -autocvar_g_vehicle_bumblebee_friction;
-
-    if(pilot.movement_x != 0)
-    {
-        if(pilot.movement_x > 0)
-            newvel += v_forward  * autocvar_g_vehicle_bumblebee_speed_forward;
-        else if(pilot.movement_x < 0)
-            newvel -= v_forward  * autocvar_g_vehicle_bumblebee_speed_forward;
-    }
-
-    if(pilot.movement_y != 0)
-    {
-        if(pilot.movement_y < 0)
-            newvel -= v_right * autocvar_g_vehicle_bumblebee_speed_strafe;
-        else if(pilot.movement_y > 0)
-            newvel += v_right * autocvar_g_vehicle_bumblebee_speed_strafe;
-        ftmp = newvel * v_right;
-        ftmp *= frametime * 0.1;
-        vehic.angles_z = bound(-15, vehic.angles_z + ftmp, 15);
-    }
-    else
-    {
-        vehic.angles_z *= 0.95;
-        if(vehic.angles_z >= -1 && vehic.angles_z <= -1)
-            vehic.angles_z = 0;
-    }
-
-    if(pilot.BUTTON_CROUCH)
-        newvel -=   v_up * autocvar_g_vehicle_bumblebee_speed_down;
-    else if (pilot.BUTTON_JUMP)
-        newvel +=  v_up * autocvar_g_vehicle_bumblebee_speed_up;
-
-    vehic.velocity  += newvel * frametime;
-    pilot.velocity = pilot.movement  = vehic.velocity;
-    setorigin(pilot,vehic.origin + '0 0 32');
-
-
-    if(vehic.vehicle_flags  & VHF_SHIELDREGEN)
-        vehicles_regen(dmg_time, vehicle_shield, autocvar_g_vehicle_bumblebee_shield, autocvar_g_vehicle_bumblebee_shield_regen_pause, autocvar_g_vehicle_bumblebee_shield_regen, frametime);
-
-    if(vehic.vehicle_flags  & VHF_HEALTHREGEN)
-        vehicles_regen(dmg_time, vehicle_health, autocvar_g_vehicle_bumblebee_health, autocvar_g_vehicle_bumblebee_health_regen_pause, autocvar_g_vehicle_bumblebee_health_regen, frametime);
-
-    if(vehic.vehicle_flags  & VHF_ENERGYREGEN)
-        vehicles_regen(cnt, vehicle_energy, autocvar_g_vehicle_bumblebee_energy, autocvar_g_vehicle_bumblebee_energy_regen_pause, autocvar_g_vehicle_bumblebee_energy_regen, frametime);
-
-    VEHICLE_UPDATE_PLAYER(health, bumblebee);
-    VEHICLE_UPDATE_PLAYER(energy, bumblebee);
-    if(vehic.vehicle_flags & VHF_HASSHIELD)
-        VEHICLE_UPDATE_PLAYER(shield, bumblebee);
-
-    pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = pilot.BUTTON_CROUCH = 0;
-    self = pilot;
-
-    return 1;
-}
-
-void bumb_think()
-{
-    self.velocity = self.velocity * 0.99;
-    self.nextthink = time + 0.1;
-}
-
-void bumb_enter()
-{
-    self.touch  = bumb_gunner_enter;
-}
-
-void bumb_exit(float eject)
-{
-    self.owner = world;
-    self.touch = vehicles_touch;
-}
-
-void bumb_spawn()
-{
-    self.vehicle_health = autocvar_g_vehicle_bumblebee_health;
-    self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
-    self.movetype       = MOVETYPE_TOSS;
-    self.solid          = SOLID_BBOX;
-    //self.vehicle_energy = 1;
-    self.movetype = MOVETYPE_FLY;
-    setorigin(self, self.origin + '0 0 25');
-}
-
-void bumb_die()
-{
-    self.health       = 0;
-    self.event_damage = SUB_Null;
-    self.solid        = SOLID_CORPSE;
-    self.takedamage   = DAMAGE_NO;
-    self.deadflag     = DEAD_DYING;
-    self.movetype     = MOVETYPE_BOUNCE;
-
-    pointparticles(particleeffectnum("rocket_explode"), findbetterlocation (self.origin, 16), '0 0 0', 1);
-}
-
-void bumb_dinit()
-{
-    if not (vehicle_initialize(
-             "Bumblebee",
-             "models/vehicles/bumblebee_body.dpm",
-             "",
-             "models/vehicles/spiderbot_cockpit.dpm",
-             "", "", "tag_viewport",
-             HUD_BUMBLEBEE,
-             BUMB_MIN, BUMB_MAX,
-             FALSE,
-             bumb_spawn, autocvar_g_vehicle_bumblebee_respawntime,
-             bumb_pilot_frame,
-             bumb_enter, bumb_exit,
-             bumb_die,   bumb_think,
-             FALSE))
-    {
-        remove(self);
-        return;
-    }
-    self.gun1 = spawn();
-    setmodel(self.gun1, "models/vehicles/bumblebee_ray.dpm");
-    setattachment(self.gun1, self, "tag_hardpoint03");
-
-    self.gun1 = spawn();
-    self.gun2 = spawn();
-
-    self.gun1.owner = self;
-    self.gun2.owner = self;
-
-    setmodel(self.gun1, "models/vehicles/bumblebee_plasma_right.dpm");
-    setmodel(self.gun2, "models/vehicles/bumblebee_plasma_left.dpm");
-
-    setattachment(self.gun1, self, "tag_hardpoint01");
-    setattachment(self.gun2, self, "tag_hardpoint02");
-
-    vector ofs;
-    ofs = gettaginfo(self, gettagindex(self, "tag_hardpoint01"));
-    ofs -= self.origin;
-    setattachment(self.gun1, self, "");
-    setorigin(self.gun1, ofs);
-
-    ofs = gettaginfo(self, gettagindex(self, "tag_hardpoint02"));
-    ofs -= self.origin;
-    setattachment(self.gun2, self, "");
-    setorigin(self.gun2, ofs);
-
-
-}
-
-void spawnfunc_vehicle_bumblebee()
-{
-
-    precache_model ("models/vehicles/bumblebee_body.dpm");
-    precache_model ("models/vehicles/bumblebee_plasma_left.dpm");
-    precache_model ("models/vehicles/bumblebee_plasma_right.dpm");
-    precache_model ("models/vehicles/bumblebee_ray.dpm");
-
-    //vehicles_configcheck("vehicle_bumblebee.cfg", autocvar_g_vehicle_bumblebee_health);
-
-    if(autocvar_g_vehicle_bumblebee_energy)
-        if(autocvar_g_vehicle_bumblebee_energy_regen)
-            self.vehicle_flags |= VHF_ENERGYREGEN;
-
-    if(autocvar_g_vehicle_bumblebee_shield)
-        self.vehicle_flags |= VHF_HASSHIELD;
-
-    if(autocvar_g_vehicle_bumblebee_shield_regen)
-        self.vehicle_flags |= VHF_SHIELDREGEN;
-
-    if(autocvar_g_vehicle_bumblebee_health_regen)
-        self.vehicle_flags |= VHF_HEALTHREGEN;
-
-    self.think = bumb_dinit;
-    self.nextthink = time + 1;
-}
-#endif // SVQC
-
-#ifdef CSQC
-void bumblebee_draw()
-{
-
-}
-
-void bumblebee_draw2d()
-{
-
-}
-
-void bumblebee_read_extra()
-{
-
-}
-
-void vehicle_bumblebee_assemble()
-{
-
-}
-#endif //CSQC
diff --git a/qcsrc/server/vehicles/collision.qc b/qcsrc/server/vehicles/collision.qc
deleted file mode 100644 (file)
index 11488a0..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-vector collision_force;
-vector collision_angle;
-
-vector bb1[9];
-vector bb2[9];
-
-float collision_run()
-{
-    vector vtmp, vmin, vmax, vrot, vforce, vtmp2, vtmp3;
-    float i, fvel, bcol;
-
-
-    // Extract the 8 bbox corners from mins/maxs for self
-    vmax = self.maxs;
-    vmin = self.mins;
-    bb1[0] = vmax;
-    vtmp   = vmax; vtmp_x = vmin_x; bb1[1] = vtmp;
-    vtmp   = vmax; vtmp_y = vmin_y; bb1[2] = vtmp;
-    vtmp   = vmin; vtmp_z = vmax_z; bb1[3] = vtmp;
-    bb1[4] = vmin;
-    vtmp   = vmin; vtmp_x = vmax_x; bb1[5] = vtmp;
-    vtmp   = vmin; vtmp_y = vmax_y; bb1[6] = vtmp;
-    vtmp   = vmax; vtmp_z = vmin_z; bb1[7] = vtmp;
-
-    makevectors(self.angles + '-2 0 0' * self.angles_x);
-    bcol = 0;
-
-    // Pass1: Transform by rotation, ajust points by impact/s
-    for(i = 8; i >= 0; --i)
-    {
-        vtmp = bb1[i];
-        vtmp = self.origin + vtmp_x * v_forward - vtmp_y * v_right + vtmp_z * v_up;
-        traceline(self.origin, vtmp, MOVE_WORLDONLY, self);
-        te_lightning1(world,self.origin,vtmp);
-        if(trace_fraction != 1.0)
-        {
-            vforce += (trace_endpos - vtmp);
-            vtmp3 = self.origin + self.velocity * frametime;
-            vtmp2 =  vectoangles(normalize(vtmp - vtmp3));
-            vrot   += (vectoangles(normalize(trace_endpos - vtmp3)) - vtmp2);
-            bcol += 1;
-        }
-    }
-
-    if(bcol)
-    {
-
-        vtmp = self.origin + self.velocity * frametime;
-        self.angles += vrot * frametime;
-        self.velocity += vforce * frametime;
-
-    }
-
-}
-
diff --git a/qcsrc/server/vehicles/network.qc b/qcsrc/server/vehicles/network.qc
deleted file mode 100644 (file)
index 688aa7c..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-#ifdef VEHICLES_CSQC
-// SendFlags
-float VSF_SETUP       = 1;          /// Send vehicle type etc
-float VSF_ORIGIN      = 2;          /// Send location
-float VSF_MOVEMENT    = 4;          /// Send movement update (and angles)
-float VSF_AVEL        = 8;          /// Send Angular velocity
-float VSF_STATS       = 16;         /// Send ammo, health etc
-float VSF_EXTRA       = 32;         /// Send additional data (turret rotations etc). Handeld per vehicle type.
-float VSF_ANIMINFO    = 64;         /// Animation info
-float VSF_FULL_UPDATE = 16777215;    /// Send everything
-
-float VSX_FAR   = 1;
-float VSX_OWNER = 2;
-float VSX_GUN1  = 4;
-float VSX_GUN2  = 8;
-
-#ifdef SVQC
-#define VSX_FARDISTANCE 2000
-float send_vehile(entity to, float sf)
-{
-       float dist, xf;
-
-    var void WriteFunc(float, float);
-
-    dist = vlen(self.origin - to.origin);
-    if(to == self.owner)
-        xf |= VSX_OWNER;
-    else if(dist > VSX_FARDISTANCE)
-        xf |= VSX_FAR;
-
-       // Always send a movement and origin to owner
-       if(to == self.owner)
-           sf |= VSF_ORIGIN | VSF_MOVEMENT;
-
-       WriteByte(MSG_ENTITY, ENT_CLIENT_VEHICLE);
-
-       // We need to know client-side what was sent
-       WriteByte(MSG_ENTITY, sf);
-       WriteByte(MSG_ENTITY, xf);
-
-       if(sf & VSF_SETUP)
-       {
-        WriteByte(MSG_ENTITY,  self.hud);        //vehicle type = hud
-        WriteByte(MSG_ENTITY,  self.team);
-        WriteShort(MSG_ENTITY, self.colormap);
-        WriteShort(MSG_ENTITY, self.vehicle_flags);
-       }
-
-    if(sf & VSF_ORIGIN)
-    {
-        WriteFunc = ((xf & VSX_FAR) ? WriteShort : WriteCoord);
-        WriteFunc(MSG_ENTITY, self.origin_x);
-        WriteFunc(MSG_ENTITY, self.origin_y);
-        WriteFunc(MSG_ENTITY, self.origin_z);
-    }
-
-    if(sf & VSF_MOVEMENT)
-    {
-        WriteFunc = ((xf & VSX_FAR) ? WriteShort : WriteCoord);
-        WriteFunc(MSG_ENTITY, self.velocity_x);
-        WriteFunc(MSG_ENTITY, self.velocity_y);
-        WriteFunc(MSG_ENTITY, self.velocity_z);
-
-        WriteFunc = ((xf & VSX_FAR) ? WriteShort : WriteAngle);
-        WriteFunc(MSG_ENTITY, self.angles_x);
-        WriteFunc(MSG_ENTITY, self.angles_y);
-        WriteFunc(MSG_ENTITY, self.angles_z);
-    }
-
-    if(sf & VSF_AVEL)
-    {
-        WriteFunc = ((xf & VSX_FAR) ? WriteShort : WriteCoord);
-        WriteFunc(MSG_ENTITY, self.avelocity_x);
-        WriteFunc(MSG_ENTITY, self.avelocity_y);
-        WriteFunc(MSG_ENTITY, self.avelocity_z);
-    }
-
-    if(sf & VSF_STATS)
-    {
-        WriteByte(MSG_ENTITY, self.vehicle_health);
-        if(xf & VSX_OWNER)
-        {
-            WriteByte(MSG_ENTITY, self.vehicle_shield);
-            WriteByte(MSG_ENTITY, self.vehicle_energy);
-
-            WriteByte(MSG_ENTITY, self.vehicle_ammo1);
-            WriteByte(MSG_ENTITY, self.vehicle_reload1);
-
-            WriteByte(MSG_ENTITY, self.vehicle_ammo2);
-            WriteByte(MSG_ENTITY, self.vehicle_reload2);
-
-        }
-    }
-
-    if(sf & VSF_EXTRA)
-        self.vehile_send_exta(to, sf);
-
-    return TRUE;
-}
-
-void net_link_vehile()
-{
-    self.SendFlags = 0xFFFFFF;
-    Net_LinkEntity(self, FALSE, 0, send_vehile);
-}
-#endif // SVQC
-
-#ifdef CSQC
-void vehicle_spiderbot_assemble()
-{
-
-}
-
-void vehicle_raptor_assemble()
-{
-
-}
-
-void vehicle_bumblebee_assemble()
-{
-
-}
-
-.float lastupdate;
-void read_vehicle(float bIsNew)
-{
-    float sf, xf;
-    var float ReadFunc();
-
-    sf = ReadByte();
-    xf = ReadByte();
-
-    if(xf & VSX_OWNER)
-        vehicle = self;
-
-       if(sf & VSF_SETUP)
-       {
-        self.vehicle_hud   = ReadByte();
-        self.team          = ReadByte();
-        self.colormap      = ReadShort();
-        self.vehicle_flags = ReadShort();
-
-        switch(self.vehicle_hud)
-        {
-            case HUD_WAKIZASHI:
-                vehicle_racer_assemble();
-                break;
-            case HUD_SPIDERBOT:
-                vehicle_spiderbot_assemble();
-                break;
-            case HUD_RAPTOR:
-                vehicle_raptor_assemble();
-                break;
-            case HUD_BUMBLEBEE:
-                vehicle_bumblebee_assemble();
-                break;
-            default:
-                break;
-        }
-       }
-
-       if(self.vehicle_hud == HUD_WAKIZASHI && xf & VSX_OWNER)
-       {
-
-        vehicle_hudmodel.owner  = self;
-       }
-
-    //if(xf & VSX_FAR)
-    //    dprint("Client vehicle faaar set\n");
-
-    if(sf & VSF_ORIGIN)
-    {
-        ReadFunc = ((xf & VSX_FAR) ? ReadShort : ReadCoord);
-        self.origin_x = ReadFunc();
-        self.origin_y = ReadFunc();
-        self.origin_z = ReadFunc();
-
-        setorigin(self, self.origin);
-        //self.lastupdate = time;
-    }
-
-    if(sf & VSF_MOVEMENT)
-    {
-        ReadFunc = ((xf & VSX_FAR) ? ReadShort : ReadCoord);
-        self.velocity_x  = ReadFunc();
-        self.velocity_y  = ReadFunc();
-        self.velocity_z  = ReadFunc();
-
-        ReadFunc = ((sf & VSX_FAR) ? ReadShort : ReadAngle);
-        self.angles_x = ReadFunc();
-        self.angles_y = ReadFunc();
-        self.angles_z = ReadFunc();
-
-        //self.lastupdate = time;
-        // self.move_velocity  = self.velocity;
-        // self.move_angles    = self.angles;
-    }
-
-    if(sf & VSF_AVEL)
-    {
-        ReadFunc = ((xf & VSX_FAR) ? ReadShort : ReadCoord);
-        self.avelocity_x = ReadFunc();
-        self.avelocity_y = ReadFunc();
-        self.avelocity_z = ReadFunc();
-
-        // self.move_avelocity  = self.avelocity;
-    }
-
-    if(sf & VSF_STATS)
-    {
-        self.vehicle_health = ReadByte();
-        if(xf & VSX_OWNER)
-        {
-            self.vehicle_shield  = ReadByte();
-            self.vehicle_energy  = ReadByte();
-            self.vehicle_ammo1   = ReadByte();
-            self.vehicle_reload1 = ReadByte();
-            self.vehicle_ammo2   = ReadByte();
-            self.vehicle_reload2 = ReadByte();
-        }
-    }
-
-    if(sf & VSF_EXTRA)
-        self.vehile_read_exta(sf);
-
-}
-
-#endif // CSQC
-#else
-#ifdef CSQC
-.float lastupdate;
-void read_vehicle(float bIsNew)
-{
-
-}
-#endif
-#endif // VEHICLES_CSQC
diff --git a/qcsrc/server/verbstack.qc b/qcsrc/server/verbstack.qc
deleted file mode 100644 (file)
index b0601af..0000000
+++ /dev/null
@@ -1,274 +0,0 @@
-/// Some default stacks.
-.entity verbs_idle;
-.entity verbs_attack;
-.entity verbs_move;
-//.entity vchain;
-
-/// This global gets set to the verb in question each time the stack manager calls verb_call
-entity verb;
-//.entity current_verb;
-//.float verb_done;
-
-/// Execure this verb
-#define VCM_DO     0
-/// Return the value of this verb. Return VS_CALL_REMOVE to delete it.
-#define VCM_EVAL   1
-/// This verb is beeing removed NOW (not sent when verb_call returns VS_CALL_REMOVE)
-#define VCM_REMOVE 2
-
-/// Verb callback
-.float(float message) verb_call;
-
-/// Points to this verb's stack.
-.entity  verbstack;
-
-/// Static value of this verb
-.float verb_static_value;
-
-/// verb_call returns this when a verb in not doable
-#define VS_CALL_NO        0
-/// verb_call(VCM_DO) returns this when a verb is executing
-#define VS_CALL_YES_DOING -1
-/// verb_call(VCM_DO) returns this when a verb did execure and is done
-#define VS_CALL_YES_DONE  -2
-/// verb_call(VCM_DO) returns this when a verb should be deleted by the stack manager
-#define VS_CALL_REMOVE    -3
-
-/*
-void verbstack_updatechain(entity stack)
-{
-    entity vrb, v;
-    if not (stack)
-        return;
-
-    dprint("verbstack_updatechain\n");
-
-    vrb = findchainentity(verbstack, stack);
-    if not (vrb)
-    {
-        stack.vchain = world;
-        return;
-    }
-
-    stack.vchain = vrb;
-    v = vrb;
-
-    while(vrb)
-    {
-        vrb = vrb.chain;
-
-
-    }
-}
-
-void verbstack_remove(entity vverb)
-{
-    entity vstack;
-    dprint("verbstack_remove\n");
-
-    vstack = verb.verbstack;
-    remove(vverb);
-    vverb.verbstack = world;
-    verbstack_updatechain(vstack);
-
-    //vverb.think = SUB_Remove;
-    //vverb.nextthink = time;
-}
-
-void verbstack_thinkremove()
-{
-    dprint("verbstack_thinkremove\n");
-    verbstack_remove(self);
-}
-*/
-
-/**
-    Push a new verb onto the specified stack. Set vrb_life to make it time-limited.
-**/
-entity verbstack_push(entity stack, float(float eval) vrb_call, float val_static, float vrb_life,entity verb_owner)
-{
-    entity vrb;
-
-    if not(stack)
-        return world;
-
-    if not(vrb_call)
-        return world;
-
-    vrb                   = spawn();
-    vrb.owner             = verb_owner;
-    vrb.verbstack         = stack;
-    vrb.verb_call         = vrb_call;
-    vrb.verb_static_value = val_static;
-
-    vrb.classname         = "verb";
-    stack.classname       = "verbstack";
-
-    if(vrb_life)
-    {
-        //vrb.think     = verbstack_thinkremove;
-        vrb.think     = SUB_Remove;
-        vrb.nextthink = time + vrb_life;
-    }
-
-    //verbstack_updatechain(stack);
-
-    return vrb;
-}
-
-/**
-    Find the best verb in this stack and execurte it.
-    ALso remove any verbs returning VS_CALL_REMOVE on VCM_EVAL or VCM_DO
-**/
-float verbstack_pop(entity stack)
-{
-    entity vrb, bestverb, oldself;
-    float  value, bestvalue;
-
-    oldself = self;
-
-    vrb = findchainentity(verbstack,stack);
-    //vrb = stack.vchain;
-    //dprint("owner:", stack.owner.classname, " vsn:", stack.classname,"\n");
-    while(vrb)
-    {
-        //dprint("vn:", vrb.classname,"\n");
-        verb  = vrb;
-        vrb   = vrb.chain;
-        self  = verb.owner;
-        value = verb.verb_call(VCM_EVAL);
-
-        if(value < 0)
-        {
-            if(value == VS_CALL_REMOVE)
-                remove(verb);
-        }
-        else
-        {
-            if(value > bestvalue)
-            {
-                bestverb  = verb;
-                bestvalue = value;
-            }
-        }
-    }
-
-    if(bestverb)
-    {
-        verb  = bestverb;
-        self  = verb.owner;
-        value = verb.verb_call(VCM_DO);
-
-        if(value == VS_CALL_REMOVE)
-            remove(bestverb);
-    }
-
-    self = oldself;
-
-    return value;
-}
-
-float verbstack_popfifo(entity stack)
-{
-    entity oldself;
-    float ret;
-
-    oldself = self;
-    verb = findentity(stack,verbstack,stack);
-    if not (verb)
-        ret = 0;
-    else
-    {
-        self = verb.owner;
-        ret = verb.verb_call(VCM_DO);
-
-        if(ret == VS_CALL_REMOVE)
-            remove(verb);
-    }
-
-    self = oldself;
-    return ret;
-}
-
-/**
-    Find the best verb in this stack and return it.
-    ALso remove any verbs returning VS_CALL_REMOVE on VCM_EVAL.
-**/
-entity verbstack_pull(entity stack)
-{
-    entity vrb;
-    entity bestverb, oldself;
-    float  value, bestvalue;
-
-    oldself = self;
-
-    vrb = findchainentity(verbstack,stack);
-    while(vrb)
-    {
-        self = vrb.owner;
-
-        verb  = vrb;
-        vrb   = vrb.chain;
-        value = verb.verb_call(VCM_EVAL);
-
-        if(value < 0)
-        {
-            if(value == VS_CALL_REMOVE)
-                remove(verb);
-        }
-        else
-        {
-            if(value > bestvalue)
-            {
-                bestverb = verb;
-                bestvalue = value;
-            }
-        }
-    }
-
-    self = oldself;
-
-    return bestverb;
-}
-
-entity verbstack_pullfifo(entity stack)
-{
-    return findentity(stack,verbstack,stack);
-}
-
-/**
-    Delete every verb on this stack, signaling them with VCM_REMOVE first.
-**/
-void verbstack_flush(entity stack)
-{
-    entity vrb, oldself;
-
-    oldself = self;
-
-    vrb = findchainentity(verbstack,stack);
-    while(vrb)
-    {
-        self = vrb.owner;
-
-        verb = vrb;
-        vrb  = vrb.chain;
-        verb.verb_call(VCM_REMOVE);
-        remove(verb);
-    }
-
-    self = oldself;
-
-    //stack.vchain = world;
-}
-
-void verbstack_doverb(entity vrb)
-{
-    float value;
-
-    verb  = vrb;
-    self  = verb.owner;
-    value = verb.verb_call(VCM_DO);
-
-    if(value == VS_CALL_REMOVE)
-        remove(vrb);
-}