Fix monsters not attacking some targets, also fix monster paths
authorMario <mario@smbclan.net>
Fri, 13 Jan 2017 14:12:02 +0000 (00:12 +1000)
committerMario <mario@smbclan.net>
Fri, 13 Jan 2017 14:12:02 +0000 (00:12 +1000)
qcsrc/common/monsters/sv_monsters.qc
qcsrc/server/mutators/events.qh
qcsrc/server/mutators/mutator/gamemode_invasion.qc

index 8456e7a..3e90b07 100644 (file)
@@ -99,9 +99,10 @@ bool Monster_ValidTarget(entity this, entity targ)
                return false;
        }
 
-       traceline(this.origin + this.view_ofs, targ.origin, MOVE_NOMONSTERS, this);
+       vector targ_origin = ((targ.absmin + targ.absmax) * 0.5);
+       traceline(this.origin + this.view_ofs, targ_origin, MOVE_NOMONSTERS, this);
 
-       if(trace_fraction < 1)
+       if(trace_fraction < 1 && trace_ent != targ)
                return false; // solid
 
        if(autocvar_g_monsters_target_infront || (this.spawnflags & MONSTERFLAG_INFRONT))
@@ -693,7 +694,8 @@ void Monster_CalculateVelocity(entity this, vector to, vector from, float turnra
 void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed)
 {
        // update goal entity if lost
-       if(this.target2 && this.goalentity.targetname != this.target2) { this.goalentity = find(NULL, targetname, this.target2); }
+       if(this.target2 && this.target2 != "" && this.goalentity.targetname != this.target2)
+               this.goalentity = find(NULL, targetname, this.target2);
 
        if(STAT(FROZEN, this) == 2)
        {
@@ -866,9 +868,9 @@ void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed)
        else
        {
                entity e = this.goalentity; //find(NULL, targetname, this.target2);
-               if(e.target2)
+               if(e.target2 && e.target2 != "")
                        this.target2 = e.target2;
-               else if(e.target) // compatibility
+               else if(e.target && e.target != "") // compatibility
                        this.target2 = e.target;
 
                movelib_brake_simple(this, stpspeed);
index ebe03df..2d32dc9 100644 (file)
@@ -308,6 +308,7 @@ MUTATOR_HOOKABLE(MonsterDropItem, EV_MonsterDropItem);
     /** walk speed */    i(float, MUTATOR_ARGV_2_float) \
     /**/                 o(float, MUTATOR_ARGV_2_float) \
     /** move target */   i(entity, MUTATOR_ARGV_3_entity) \
+    /**/                 o(entity, MUTATOR_ARGV_3_entity) \
     /**/
 MUTATOR_HOOKABLE(MonsterMove, EV_MonsterMove);
 
index e62a392..1355134 100644 (file)
@@ -5,6 +5,9 @@
 
 #include <server/teamplay.qh>
 
+IntrusiveList g_invasion_waves;
+STATIC_INIT(g_invasion_waves) { g_invasion_waves = IL_NEW(); }
+
 IntrusiveList g_invasion_spawns;
 STATIC_INIT(g_invasion_spawns) { g_invasion_spawns = IL_NEW(); }
 
@@ -17,6 +20,13 @@ float autocvar_g_invasion_spawn_delay;
 
 .string spawnmob;
 
+spawnfunc(invasion_wave)
+{
+       if(!g_invasion) { delete(this); return; }
+
+       IL_PUSH(g_invasion_waves, this);
+}
+
 spawnfunc(invasion_spawnpoint)
 {
        if(!g_invasion) { delete(this); return; }
@@ -55,11 +65,41 @@ entity invasion_PickSpawn()
        return RandomSelection_chosen_ent;
 }
 
+entity invasion_GetWaveEntity(int wavenum)
+{
+       IL_EACH(g_invasion_waves, it.cnt == wavenum,
+       {
+               return it; // found one
+       });
+
+       // if no specific one is found, find the last existing wave ent
+       entity best = NULL;
+       IL_EACH(g_invasion_waves, it.cnt <= wavenum,
+       {
+               if(!best || it.cnt > best.cnt)
+                       best = it;
+       });
+
+       return best;
+}
+
 void invasion_SpawnChosenMonster(Monster mon)
 {
-       entity spawn_point, monster;
+       entity monster;
+       entity spawn_point = invasion_PickSpawn();
+       entity wave_ent = invasion_GetWaveEntity(inv_roundcnt);
 
-       spawn_point = invasion_PickSpawn();
+       string tospawn = "";
+       if(wave_ent && wave_ent.spawnmob && wave_ent.spawnmob != "")
+       {
+               RandomSelection_Init();
+               FOREACH_WORD(wave_ent.spawnmob, true,
+               {
+                       RandomSelection_AddString(it, 1, 1);
+               });
+
+               tospawn = RandomSelection_chosen_string;
+       }
 
        if(spawn_point == NULL)
        {
@@ -68,7 +108,7 @@ void invasion_SpawnChosenMonster(Monster mon)
                setsize(e, mon.mins, mon.maxs);
 
                if(MoveToRandomMapLocation(e, DPCONTENTS_SOLID | DPCONTENTS_CORPSE | DPCONTENTS_PLAYERCLIP, DPCONTENTS_SLIME | DPCONTENTS_LAVA | DPCONTENTS_SKY | DPCONTENTS_BODY | DPCONTENTS_DONOTENTER, Q3SURFACEFLAG_SKY, 10, 1024, 256))
-                       monster = spawnmonster(e, "", mon.monsterid, NULL, NULL, e.origin, false, false, 2);
+                       monster = spawnmonster(e, tospawn, mon.monsterid, NULL, NULL, e.origin, false, false, 2);
                else
                {
                        delete(e);
@@ -76,31 +116,35 @@ void invasion_SpawnChosenMonster(Monster mon)
                }
        }
        else // if spawnmob field falls through (unset), fallback to mon (relying on spawnmonster for that behaviour)
-               monster = spawnmonster(spawn(), spawn_point.spawnmob, mon.monsterid, spawn_point, spawn_point, spawn_point.origin, false, false, 2);
+               monster = spawnmonster(spawn(), ((spawn_point.spawnmob && spawn_point.spawnmob != "") ? spawn_point.spawnmob : tospawn), mon.monsterid, spawn_point, spawn_point, spawn_point.origin, false, false, 2);
 
        if(!monster)
                return;
 
-       if(spawn_point) monster.target2 = spawn_point.target2;
        monster.spawnshieldtime = time;
-       if(spawn_point && spawn_point.target_range) monster.target_range = spawn_point.target_range;
 
-       if(teamplay)
-       if(spawn_point && spawn_point.team && inv_monsters_perteam[spawn_point.team] > 0)
-               monster.team = spawn_point.team;
-       else
+       if(spawn_point)
        {
-               RandomSelection_Init();
-               if(inv_monsters_perteam[NUM_TEAM_1] > 0) RandomSelection_AddFloat(NUM_TEAM_1, 1, 1);
-               if(inv_monsters_perteam[NUM_TEAM_2] > 0) RandomSelection_AddFloat(NUM_TEAM_2, 1, 1);
-               if(invasion_teams >= 3) if(inv_monsters_perteam[NUM_TEAM_3] > 0) { RandomSelection_AddFloat(NUM_TEAM_3, 1, 1); }
-               if(invasion_teams >= 4) if(inv_monsters_perteam[NUM_TEAM_4] > 0) { RandomSelection_AddFloat(NUM_TEAM_4, 1, 1); }
-
-               monster.team = RandomSelection_chosen_float;
+               if(spawn_point.target_range)
+                       monster.target_range = spawn_point.target_range;
+               monster.target2 = spawn_point.target2;
        }
 
        if(teamplay)
        {
+               if(spawn_point && spawn_point.team && inv_monsters_perteam[spawn_point.team] > 0)
+                       monster.team = spawn_point.team;
+               else
+               {
+                       RandomSelection_Init();
+                       if(inv_monsters_perteam[NUM_TEAM_1] > 0) RandomSelection_AddFloat(NUM_TEAM_1, 1, 1);
+                       if(inv_monsters_perteam[NUM_TEAM_2] > 0) RandomSelection_AddFloat(NUM_TEAM_2, 1, 1);
+                       if(invasion_teams >= 3) if(inv_monsters_perteam[NUM_TEAM_3] > 0) { RandomSelection_AddFloat(NUM_TEAM_3, 1, 1); }
+                       if(invasion_teams >= 4) if(inv_monsters_perteam[NUM_TEAM_4] > 0) { RandomSelection_AddFloat(NUM_TEAM_4, 1, 1); }
+
+                       monster.team = RandomSelection_chosen_float;
+               }
+
                monster_setupcolors(monster);
 
                if(monster.sprite)