]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/mutators/gamemode_ctf.qc
Merge remote branch 'origin/master' into samual/mutator_ctf
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / gamemode_ctf.qc
index dd16e17681249f9c92f7c493174b4200741992e8..b82e26345063eb9d9369a9b5bbb33bd7a807fde0 100644 (file)
@@ -336,7 +336,7 @@ void ctf_Handle_Throw(entity player, entity reciever, float droptype)
        WaypointSprite_Kill(player.wps_flagcarrier);
        
        if(player.wps_enemyflagcarrier)
-                       WaypointSprite_Kill(player.wps_enemyflagcarrier);
+               WaypointSprite_Kill(player.wps_enemyflagcarrier);
        
        // captureshield
        ctf_CaptureShield_Update(player, 0); // shield player from picking up flag
@@ -531,6 +531,51 @@ void ctf_CheckFlagReturn(entity flag, float returntype)
        }
 }
 
+void ctf_CheckStalemate(void)
+{
+       // declarations
+       float stale_red_flags, stale_blue_flags;
+       entity tmp_entity;
+
+       // build list of stale flags
+       for(tmp_entity = ctf_worldflaglist; tmp_entity; tmp_entity = tmp_entity.ctf_worldflagnext)
+       {
+               if(autocvar_g_ctf_flagcarrier_waypointforenemy_stalemate)
+               if(time >= tmp_entity.ctf_pickuptime + autocvar_g_ctf_flagcarrier_waypointforenemy_stalemate)
+               {
+                       tmp_entity.ctf_staleflagnext = ctf_staleflaglist; // link flag into staleflaglist
+                       ctf_staleflaglist = tmp_entity;
+                       
+                       switch(tmp_entity.team)
+                       {
+                               case COLOR_TEAM1: ++stale_red_flags; break;
+                               case COLOR_TEAM2: ++stale_blue_flags; break;
+                       }
+               }
+       }
+       
+       // if sufficient stalemate, then set up the waypointsprite and announce the stalemate if necessary
+       if(stale_red_flags && stale_blue_flags)
+       {
+               for(tmp_entity = ctf_staleflaglist; tmp_entity; tmp_entity = tmp_entity.ctf_staleflagnext)
+               {
+                       if not(tmp_entity.owner.wps_enemyflagcarrier)   
+                               WaypointSprite_Spawn("enemyflagcarrier", 0, 0, tmp_entity.owner, FLAG_WAYPOINT_OFFSET, world, tmp_entity.team, tmp_entity.owner, wps_enemyflagcarrier, TRUE, RADARICON_FLAG, WPCOLOR_ENEMYFC(tmp_entity.owner.team));
+               }
+               
+               if not(wpforenemy_announced)
+               {
+                       FOR_EACH_REALPLAYER(tmp_entity)
+                               if(tmp_entity.flagcarried)
+                                       centerprint(tmp_entity, "Stalemate! Enemies can now see you on radar!");
+                               else
+                                       centerprint(tmp_entity, "Stalemate! Flag carriers can now be seen by enemies on radar!");
+                       
+                       wpforenemy_announced = TRUE;
+               }
+       }
+}
+
 void ctf_FlagDamage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
 {
        if(ITEM_DAMAGE_NEEDKILL(deathtype))
@@ -540,7 +585,6 @@ void ctf_FlagDamage(entity inflictor, entity attacker, float damage, float death
                ctf_CheckFlagReturn(self, RETURN_NEEDKILL);
                return;
        }
-       
        if(autocvar_g_ctf_flag_return_damage) 
        {
                // reduce health and check if it should be returned
@@ -599,7 +643,7 @@ void ctf_FlagThink()
                case FLAG_DROPPED:
                {
                        if(autocvar_g_ctf_flag_dropped_floatinwater && (self.flags & FL_INWATER))
-                                       self.velocity_z = autocvar_g_ctf_flag_dropped_floatinwater;
+                               self.velocity_z = autocvar_g_ctf_flag_dropped_floatinwater;
                
                        if(autocvar_g_ctf_flag_return_dropped)
                        {
@@ -632,25 +676,12 @@ void ctf_FlagThink()
                                ImpulseCommands();
                                self = tmp_entity;
                        }
-                       
-                       if(autocvar_g_ctf_flagcarrier_waypointforenemy_time)
-                       if((time >= self.ctf_pickuptime + autocvar_g_ctf_flagcarrier_waypointforenemy_time) && !self.owner.wps_enemyflagcarrier)
+                       if(autocvar_g_ctf_flagcarrier_waypointforenemy_stalemate)
                        {
-                               WaypointSprite_Spawn("enemyflagcarrier", 0, 0, self.owner, FLAG_WAYPOINT_OFFSET, world, self.team, self.owner, wps_enemyflagcarrier, TRUE, RADARICON_FLAG, WPCOLOR_ENEMYFC(self.owner.team));
-                               
-                               if(!self.wpforenemy_announced)
+                               if(time >= wpforenemy_nextthink)
                                {
-                                       FOR_EACH_REALPLAYER(tmp_entity)
-                                       {
-                                               if(tmp_entity == self.owner)
-                                                       centerprint(tmp_entity, strcat("Enemies can now see you on radar! (held ", self.netname, " for ", ftos(autocvar_g_ctf_flagcarrier_waypointforenemy_time), " seconds)"));
-                                               else if(IsDifferentTeam(tmp_entity, self.owner))
-                                                       centerprint(tmp_entity, strcat("You can now see the enemy flag carrier on radar! (held ", self.netname, " for ", ftos(autocvar_g_ctf_flagcarrier_waypointforenemy_time), " seconds)"));
-                                               else
-                                                       centerprint(tmp_entity, strcat("Enemies can now see your flag carrier on radar! (held ", self.netname, " for ", ftos(autocvar_g_ctf_flagcarrier_waypointforenemy_time), " seconds)"));
-                                       }
-                                       
-                                       self.wpforenemy_announced = TRUE;
+                                       ctf_CheckStalemate();
+                                       wpforenemy_nextthink = time + WPFE_THINKRATE; // waypoint for enemy think rate (to reduce unnecessary spam of this check)
                                }
                        }
                        return;
@@ -757,12 +788,6 @@ void ctf_FlagTouch()
                        }
                        break;
                }
-               
-               default: // this should never happen
-               {
-                       dprint("Touch: Flag exists with no status?\n");
-                       break;
-               }
        }
 }
 
@@ -805,7 +830,8 @@ void ctf_RespawnFlag(entity flag)
        flag.ctf_dropper = world;
        flag.ctf_pickuptime = 0;
        flag.ctf_droptime = 0;
-       flag.wpforenemy_announced = FALSE;
+
+       wpforenemy_announced = FALSE;
 }
 
 void ctf_Reset()
@@ -941,13 +967,22 @@ MUTATOR_HOOKFUNCTION(ctf_PlayerPreThink)
        // scan through all the flags and notify the client about them 
        for(flag = ctf_worldflaglist; flag; flag = flag.ctf_worldflagnext)
        {
-               if(flag.ctf_status == FLAG_CARRY)
-                       if(flag.owner == self)
-                               self.items |= ((flag.items & IT_KEY2) ? IT_RED_FLAG_CARRYING : IT_BLUE_FLAG_CARRYING); // carrying: self is currently carrying the flag
-                       else 
-                               self.items |= ((flag.items & IT_KEY2) ? IT_RED_FLAG_TAKEN : IT_BLUE_FLAG_TAKEN); // taken: someone on self's team is carrying the flag
-               else if(flag.ctf_status == FLAG_DROPPED) 
-                       self.items |= ((flag.items & IT_KEY2) ? IT_RED_FLAG_LOST : IT_BLUE_FLAG_LOST); // lost: the flag is dropped somewhere on the map
+               switch(flag.ctf_status)
+               {
+                       case FLAG_CARRY:
+                       {
+                               if(flag.owner == self)
+                                       self.items |= ((flag.items & IT_KEY2) ? IT_RED_FLAG_CARRYING : IT_BLUE_FLAG_CARRYING); // carrying: self is currently carrying the flag
+                               else 
+                                       self.items |= ((flag.items & IT_KEY2) ? IT_RED_FLAG_TAKEN : IT_BLUE_FLAG_TAKEN); // taken: someone on self's team is carrying the flag
+                               break;
+                       }
+                       case FLAG_DROPPED:
+                       {
+                               self.items |= ((flag.items & IT_KEY2) ? IT_RED_FLAG_LOST : IT_BLUE_FLAG_LOST); // lost: the flag is dropped somewhere on the map
+                               break;
+                       }
+               }
        }
        
        // item for stopping players from capturing the flag too often
@@ -970,12 +1005,17 @@ MUTATOR_HOOKFUNCTION(ctf_PlayerDamage) // for changing damage and force values t
                        frag_damage *= autocvar_g_ctf_flagcarrier_selfdamagefactor;
                        frag_force *= autocvar_g_ctf_flagcarrier_selfforcefactor;
                }
-               else // damage done everyone else
+               else // damage done to everyone else
                {
                        frag_damage *= autocvar_g_ctf_flagcarrier_damagefactor;
                        frag_force *= autocvar_g_ctf_flagcarrier_forcefactor;
                }
        }
+       else if(frag_target.flagcarried && (frag_target.deadflag == DEAD_NO) && IsDifferentTeam(frag_target, frag_attacker)) // if the target is a flagcarrier
+       {
+               if(autocvar_g_ctf_flagcarrier_auto_helpme_when_damaged > frag_target.health)
+                       WaypointSprite_HelpMePing(frag_target.wps_flagcarrier); // TODO: only do this if there is a significant loss of health?
+       }
        return 0;
 }