From: Samual Date: Fri, 30 Mar 2012 17:50:04 +0000 (-0400) Subject: Many more bug fixes/new features/cleanups X-Git-Tag: xonotic-v0.7.0~240^2~160 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=e54e29f95e33beac18f206d85a0b59a891b0a8e4;p=xonotic%2Fxonotic-data.pk3dir.git Many more bug fixes/new features/cleanups --- diff --git a/defaultXonotic.cfg b/defaultXonotic.cfg index e979d556b..663db3f89 100644 --- a/defaultXonotic.cfg +++ b/defaultXonotic.cfg @@ -591,7 +591,7 @@ set gamecfg 1 // "deathmatch" // ctf set g_ctf 0 "Capture The Flag: take the enemy flag and bring it to yours at your base to score" -set g_ctf_flag_returntime 30 +set g_ctf_flag_returntime 15 set g_ctf_flagcarrier_selfdamage 1 set g_ctf_flagcarrier_selfforce 1 set g_ctf_fullbrightflags 0 @@ -599,8 +599,9 @@ set g_ctf_dynamiclights 0 set g_ctf_flag_damageforcescale 2 set g_ctf_allow_drop 1 "dropping allows circumventing carrierkill score, so enable this with care!" set g_ctf_reverse 0 "if enabled, flags positions are switched: you have to capture the enemy's flag from your own base by bringing it to your own flag in the enemy base" -set g_balance_ctf_delay_collect 1.0 -set g_balance_ctf_damageforcescale 1 +set g_ctf_flag_collect_delay 1 +set g_ctf_flag_health 0 +set g_ctf_flag_take_damage 0 set g_ctf_shield_max_ratio 0 "shield at most this percentage of a team from the enemy flag (try: 0.4 for 40%)" set g_ctf_shield_min_negscore 20 "shield the player from the flag if he's got this negative amount of points or less" diff --git a/qcsrc/server/autocvars.qh b/qcsrc/server/autocvars.qh index 6d3cdd9ef..156375002 100644 --- a/qcsrc/server/autocvars.qh +++ b/qcsrc/server/autocvars.qh @@ -179,8 +179,6 @@ float autocvar_g_balance_crylink_secondary_speed; float autocvar_g_balance_crylink_secondary_spread; float autocvar_g_balance_crylink_reload_ammo; float autocvar_g_balance_crylink_reload_time; -float autocvar_g_balance_ctf_damageforcescale; -float autocvar_g_balance_ctf_delay_collect; float autocvar_g_balance_curse_empathy_minhealth; float autocvar_g_balance_curse_empathy_takedamage; float autocvar_g_balance_curse_slow_atkrate; @@ -768,13 +766,16 @@ float autocvar_g_ctf_dynamiclights; string autocvar_g_ctf_flag_blue_model; float autocvar_g_ctf_flag_blue_skin; float autocvar_g_ctf_flag_capture_effects; +float autocvar_g_ctf_flag_collect_delay; float autocvar_g_ctf_flag_damageforcescale; float autocvar_g_ctf_flag_glowtrails; +float autocvar_g_ctf_flag_health; float autocvar_g_ctf_flag_pickup_effects; float autocvar_g_ctf_flag_pickup_verbosename; string autocvar_g_ctf_flag_red_model; float autocvar_g_ctf_flag_red_skin; float autocvar_g_ctf_flag_returntime; +float autocvar_g_ctf_flag_take_damage; float autocvar_g_ctf_flagcarrier_selfdamage; float autocvar_g_ctf_flagcarrier_selfforce; float autocvar_g_ctf_fullbrightflags; diff --git a/qcsrc/server/bot/havocbot/role_ctf.qc b/qcsrc/server/bot/havocbot/role_ctf.qc index fe7b732ac..74be6e766 100644 --- a/qcsrc/server/bot/havocbot/role_ctf.qc +++ b/qcsrc/server/bot/havocbot/role_ctf.qc @@ -143,7 +143,7 @@ void havocbot_goalrating_ctf_ourstolenflag(float ratingscale) mf = havocbot_ctf_find_flag(self); - if(mf.cnt == FLAG_BASE) + if(mf.ctf_status == FLAG_BASE) return; if(mf.tag_entity) @@ -157,7 +157,7 @@ void havocbot_goalrating_ctf_droppedflags(float ratingscale, vector org, float r while (head) { // flag is out in the field - if(head.cnt != FLAG_BASE) + if(head.ctf_status != FLAG_BASE) if(head.tag_entity==world) // dropped { if(radius) @@ -295,7 +295,7 @@ void havocbot_role_ctf_escort() // If enemy flag is back on the base switch to previous role ef = havocbot_ctf_find_enemy_flag(self); - if(ef.cnt==FLAG_BASE) + if(ef.ctf_status==FLAG_BASE) { self.havocbot_role = self.havocbot_previous_role; self.havocbot_role_timeout = 0; @@ -304,7 +304,7 @@ void havocbot_role_ctf_escort() // If the flag carrier reached the base switch to defense mf = havocbot_ctf_find_flag(self); - if(mf.cnt!=FLAG_BASE) + if(mf.ctf_status!=FLAG_BASE) if(vlen(ef.origin - mf.dropped_origin) < 300) { havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_DEFENSE); @@ -359,7 +359,7 @@ void havocbot_role_ctf_offense() ef = havocbot_ctf_find_enemy_flag(self); // Own flag stolen - if(mf.cnt!=FLAG_BASE) + if(mf.ctf_status!=FLAG_BASE) { if(mf.tag_entity) pos = mf.tag_entity.origin; @@ -375,7 +375,7 @@ void havocbot_role_ctf_offense() } // Escort flag carrier - if(ef.cnt!=FLAG_BASE) + if(ef.ctf_status!=FLAG_BASE) { if(ef.tag_entity) pos = ef.tag_entity.origin; @@ -437,7 +437,7 @@ void havocbot_role_ctf_retriever() // If flag is back on the base switch to previous role mf = havocbot_ctf_find_flag(self); - if(mf.cnt==FLAG_BASE) + if(mf.ctf_status==FLAG_BASE) { havocbot_ctf_reset_role(self); return; @@ -484,7 +484,7 @@ void havocbot_role_ctf_middle() } mf = havocbot_ctf_find_flag(self); - if(mf.cnt!=FLAG_BASE) + if(mf.ctf_status!=FLAG_BASE) { havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_RETRIEVER); return; @@ -536,7 +536,7 @@ void havocbot_role_ctf_defense() // If own flag was captured mf = havocbot_ctf_find_flag(self); - if(mf.cnt!=FLAG_BASE) + if(mf.ctf_status!=FLAG_BASE) { havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_RETRIEVER); return; @@ -635,14 +635,14 @@ void havocbot_ctf_reset_role(entity bot) ef = havocbot_ctf_find_enemy_flag(bot); // Retrieve stolen flag - if(mf.cnt!=FLAG_BASE) + if(mf.ctf_status!=FLAG_BASE) { havocbot_role_ctf_setrole(bot, HAVOCBOT_CTF_ROLE_RETRIEVER); return; } // If enemy flag is taken go to the middle to intercept pursuers - if(ef.cnt!=FLAG_BASE) + if(ef.ctf_status!=FLAG_BASE) { havocbot_role_ctf_setrole(bot, HAVOCBOT_CTF_ROLE_MIDDLE); return; diff --git a/qcsrc/server/constants.qh b/qcsrc/server/constants.qh index b95c72613..aec1e3256 100644 --- a/qcsrc/server/constants.qh +++ b/qcsrc/server/constants.qh @@ -142,11 +142,6 @@ float MSG_ENTITY = 5; // csqc float TE_BEAM = 13; // grappling hook -// CTF -float FLAG_BASE = 1; -float FLAG_CARRY = 2; -float FLAG_DROPPED = 3; - float COLOR_TEAM1 = 5; // red float COLOR_TEAM2 = 14; // blue float COLOR_TEAM3 = 13; // yellow diff --git a/qcsrc/server/defs.qh b/qcsrc/server/defs.qh index f324ef115..62d65791d 100644 --- a/qcsrc/server/defs.qh +++ b/qcsrc/server/defs.qh @@ -569,7 +569,6 @@ float servertime, serverprevtime, serverframetime; string matchid; .float hitplotfh; -.string noise4; .float last_pickup; diff --git a/qcsrc/server/mutators/gamemode_ctf.qc b/qcsrc/server/mutators/gamemode_ctf.qc index acb005b09..3881db9aa 100644 --- a/qcsrc/server/mutators/gamemode_ctf.qc +++ b/qcsrc/server/mutators/gamemode_ctf.qc @@ -82,44 +82,42 @@ void ctf_CaptureShield_Update(entity player, float wanted_status) float ctf_CaptureShield_Customize() { - if not(other.ctf_captureshielded) - return FALSE; - if(self.team == other.team) - return FALSE; + if not(other.ctf_captureshielded) { return FALSE; } + if(self.team == other.team) { return FALSE; } + return TRUE; } void ctf_CaptureShield_Touch() { - if not(other.ctf_captureshielded) - return; - if(self.team == other.team) - return; - vector mymid; - vector othermid; - mymid = (self.absmin + self.absmax) * 0.5; - othermid = (other.absmin + other.absmax) * 0.5; + if not(other.ctf_captureshielded) { return; } + if(self.team == other.team) { return; } + + vector mymid = (self.absmin + self.absmax) * 0.5; + vector othermid = (other.absmin + other.absmax) * 0.5; + Damage(other, self, self, 0, DEATH_HURTTRIGGER, mymid, normalize(othermid - mymid) * ctf_captureshield_force); Send_CSQC_Centerprint_Generic(other, CPID_CTF_CAPTURESHIELD, "^3You are ^4shielded^3 from the flag\n^3for ^1too many unsuccessful attempts^3 to capture.\n\n^3Get some defensive scores before trying again.", 5, 0); } void ctf_CaptureShield_Spawn(entity flag) { - entity e; - e = spawn(); - e.enemy = self; - e.team = self.team; - e.touch = ctf_CaptureShield_Touch; - e.customizeentityforclient = ctf_CaptureShield_Customize; - e.classname = "ctf_captureshield"; - e.effects = EF_ADDITIVE; - e.movetype = MOVETYPE_NOCLIP; - e.solid = SOLID_TRIGGER; - e.avelocity = '7 0 11'; - setorigin(e, self.origin); - setmodel(e, "models/ctf/shield.md3"); - e.scale = 0.5; - setsize(e, e.scale * e.mins, e.scale * e.maxs); + entity shield = spawn(); + + shield.enemy = self; + shield.team = self.team; + shield.touch = ctf_CaptureShield_Touch; + shield.customizeentityforclient = ctf_CaptureShield_Customize; + shield.classname = "ctf_captureshield"; + shield.effects = EF_ADDITIVE; + shield.movetype = MOVETYPE_NOCLIP; + shield.solid = SOLID_TRIGGER; + shield.avelocity = '7 0 11'; + shield.scale = 0.5; + + setorigin(shield, self.origin); + setmodel(shield, "models/ctf/shield.md3"); + setsize(shield, shield.scale * shield.mins, shield.scale * shield.maxs); } @@ -142,8 +140,8 @@ void ctf_Handle_Drop(entity player) flag.movetype = MOVETYPE_TOSS; flag.solid = SOLID_TRIGGER; flag.takedamage = DAMAGE_YES; + flag.health = flag.max_flag_health; flag.velocity = ('0 0 200' + ('0 100 0' * crandom()) + ('100 0 0' * crandom())); - flag.pain_finished = time + autocvar_g_ctf_flag_returntime; // replace this later flag.ctf_droptime = time; flag.ctf_dropperid = player.playerid; @@ -151,7 +149,7 @@ void ctf_Handle_Drop(entity player) // messages and sounds Send_KillNotification(player.netname, flag.netname, "", INFO_LOSTFLAG, MSG_INFO); - sound(flag, CH_TRIGGER, flag.noise4, VOL_BASE, ATTN_NONE); + sound(flag, CH_TRIGGER, flag.snd_flag_dropped, VOL_BASE, ATTN_NONE); ctf_EventLog("dropped", player.team, player); // scoring @@ -163,6 +161,12 @@ void ctf_Handle_Drop(entity player) WaypointSprite_Ping(player.wps_flagcarrier); WaypointSprite_Kill(player.wps_flagcarrier); + if(autocvar_g_ctf_flag_returntime || (autocvar_g_ctf_flag_take_damage && autocvar_g_ctf_flag_health)) + { + WaypointSprite_UpdateMaxHealth(flag.wps_flagdropped, flag.max_flag_health); + WaypointSprite_UpdateHealth(flag.wps_flagdropped, flag.health); + } + // captureshield ctf_CaptureShield_Update(player, 0); // shield only @@ -202,7 +206,7 @@ void ctf_Handle_Capture(entity flag, entity player) // messages and sounds Send_KillNotification(player.netname, player.flagcarried.netname, cap_message, INFO_CAPTUREFLAG, MSG_INFO); - sound(player, CH_TRIGGER, flag.noise2, VOL_BASE, ATTN_NONE); // "ctf/*_capture.wav" + sound(player, CH_TRIGGER, flag.snd_flag_capture, VOL_BASE, ATTN_NONE); // "ctf/*_capture.wav" ctf_EventLog("capture", player.flagcarried.team, player); // scoring @@ -229,7 +233,7 @@ void ctf_Handle_Return(entity flag, entity player) { // messages and sounds Send_KillNotification (player.netname, flag.netname, "", INFO_RETURNFLAG, MSG_INFO); - sound(player, CH_TRIGGER, flag.noise1, VOL_BASE, ATTN_NONE); + sound(player, CH_TRIGGER, flag.snd_flag_returned, VOL_BASE, ATTN_NONE); ctf_EventLog("return", flag.team, player); // scoring @@ -269,7 +273,7 @@ void ctf_Handle_Pickup_Base(entity flag, entity player) // messages and sounds Send_KillNotification (player.netname, flag.netname, "", INFO_GOTFLAG, MSG_INFO); - sound(player, CH_TRIGGER, flag.noise, VOL_BASE, ATTN_NONE); + sound(player, CH_TRIGGER, flag.snd_flag_taken, VOL_BASE, ATTN_NONE); ctf_EventLog("steal", flag.team, player); verbosename = ((autocvar_g_ctf_flag_pickup_verbosename) ? strcat("(", player.netname, ")") : ""); // replace TRUE with an autocvar for it. FOR_EACH_PLAYER(tmp_player) @@ -304,7 +308,7 @@ void ctf_Handle_Pickup_Base(entity flag, entity player) void ctf_Handle_Pickup_Dropped(entity flag, entity player) // make sure this works { // declarations - float returnscore = bound(0, (flag.pain_finished - time) / autocvar_g_ctf_flag_returntime, 1); // can this be division by zero? + float returnscore = bound(0, (flag.pain_finished - time) / autocvar_g_ctf_flag_returntime, 1); // can this be division by zero? FIXME entity tmp_player; // temporary entity which the FOR_EACH_PLAYER loop uses to scan players string verbosename; // holds the name of the player OR no name at all for printing in the centerprints @@ -317,6 +321,7 @@ void ctf_Handle_Pickup_Dropped(entity flag, entity player) // make sure this wor // set up the flag flag.movetype = MOVETYPE_NONE; flag.takedamage = DAMAGE_NO; + flag.health = flag.max_flag_health; flag.solid = SOLID_NOT; flag.angles = '0 0 0'; //flag.ctf_pickuptime = time; // don't update pickuptime since this isn't a real steal. @@ -325,7 +330,7 @@ void ctf_Handle_Pickup_Dropped(entity flag, entity player) // make sure this wor // messages and sounds Send_KillNotification (player.netname, flag.netname, "", INFO_PICKUPFLAG, MSG_INFO); - sound (player, CH_TRIGGER, flag.noise, VOL_BASE, ATTN_NONE); + sound (player, CH_TRIGGER, flag.snd_flag_taken, VOL_BASE, ATTN_NONE); ctf_EventLog("pickup", flag.team, player); verbosename = ((autocvar_g_ctf_flag_pickup_verbosename) ? strcat("(", player.netname, ")") : ""); FOR_EACH_PLAYER(tmp_player) @@ -360,12 +365,34 @@ void ctf_Handle_Pickup_Dropped(entity flag, entity player) // make sure this wor // Main Flag Functions // =================== +void ctf_CheckFlagReturn(entity flag) +{ + if(flag.wps_flagdropped) { WaypointSprite_UpdateHealth(flag.wps_flagdropped, flag.health); } + + if((flag.health <= 0) || (time > flag.ctf_droptime + autocvar_g_ctf_flag_returntime)) + { + bprint("The ", flag.netname, " has returned to base\n"); + sound(flag, CH_TRIGGER, flag.snd_flag_respawn, VOL_BASE, ATTN_NONE); + ctf_EventLog("returned", flag.team, world); + ctf_RespawnFlag(flag); + } +} + +void ctf_FlagDamage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) +{ + if(autocvar_g_ctf_flag_take_damage) + { + self.health = self.health - damage; + ctf_CheckFlagReturn(self); + } +} + void ctf_FlagThink() { // declarations entity tmp_entity; - self.nextthink = time + 0.2; // only 5 fps, more is unnecessary. + self.nextthink = time + FLAG_THINKRATE; // only 5 fps, more is unnecessary. // captureshield if(self == ctf_worldflaglist) // only for the first flag @@ -379,38 +406,31 @@ void ctf_FlagThink() if(!trace_startsolid) // can we resize it without getting stuck? setsize(self, FLAG_MIN, FLAG_MAX); } - //if(self.owner.classname == "player" || (self.owner.deadflag) || (self.owner.flagcarried != self)) { - // dprint("CANNOT HAPPEN - player dead and STILL had a flag!\n"); - // ctf_Handle_Drop(self.owner); - // return; } - // main think method - switch(self.ctf_status) + switch(self.ctf_status) { case FLAG_BASE: // nothing to do here return; case FLAG_DROPPED: - if(time > self.ctf_droptime + autocvar_g_ctf_flag_returntime) + if(autocvar_g_ctf_flag_returntime) { - bprint("The ", self.netname, " has returned to base\n"); - sound(self, CH_TRIGGER, self.noise3, VOL_BASE, ATTN_NONE); - ctf_EventLog("returned", self.team, world); - ctf_RespawnFlag(self); - } + self.health -= ((self.max_flag_health / autocvar_g_ctf_flag_returntime) * FLAG_THINKRATE); + ctf_CheckFlagReturn(self); + } return; case FLAG_CARRY: if((self.owner) && (self.speedrunning) && (ctf_captimerecord) && (time >= self.ctf_pickuptime + ctf_captimerecord)) { bprint("The ", self.netname, " became impatient after ", ftos_decimals(ctf_captimerecord, 2), " seconds and returned itself\n"); - sound (self, CH_TRIGGER, self.noise3, VOL_BASE, ATTN_NONE); - - self.owner.impulse = 141; // returning! + sound(self, CH_TRIGGER, self.snd_flag_respawn, VOL_BASE, ATTN_NONE); + ctf_EventLog("returned", self.team, world); + ctf_RespawnFlag(tmp_entity); tmp_entity = self; self = self.owner; - ctf_RespawnFlag(tmp_entity); + self.impulse = CHIMPULSE_SPEEDRUN; // move the player back to the waypoint they set ImpulseCommands(); self = tmp_entity; } @@ -430,7 +450,7 @@ void ctf_FlagTouch() || ((trace_dpstartcontents | trace_dphitcontents) & (DPCONTENTS_SLIME | DPCONTENTS_LAVA | DPCONTENTS_NODROP))) { // The flag fell off the map or into lava/slime, respawn it since players can't get to it bprint("The ", self.netname, " has returned to base\n"); - sound (self, CH_TRIGGER, self.noise3, VOL_BASE, ATTN_NONE); + sound (self, CH_TRIGGER, self.snd_flag_respawn, VOL_BASE, ATTN_NONE); ctf_EventLog("returned", self.team, world); ctf_RespawnFlag(self); return; @@ -456,7 +476,7 @@ void ctf_FlagTouch() case FLAG_DROPPED: if(other.team == self.team) ctf_Handle_Return(self, other); // other just returned his own flag - else if((!other.flagcarried) && ((other.playerid != self.ctf_dropperid) || (time > self.ctf_droptime + autocvar_g_balance_ctf_delay_collect))) + else if((!other.flagcarried) && ((other.playerid != self.ctf_dropperid) || (time > self.ctf_droptime + autocvar_g_ctf_flag_collect_delay))) ctf_Handle_Pickup_Dropped(self, other); // other just picked up a dropped enemy flag break; @@ -490,6 +510,7 @@ void ctf_RespawnFlag(entity flag) setorigin(flag, flag.ctf_spawnorigin); // replace with flag.ctf_spawnorigin flag.movetype = ((flag.noalign) ? MOVETYPE_NONE : MOVETYPE_TOSS); flag.takedamage = DAMAGE_NO; + flag.health = flag.max_flag_health; flag.solid = SOLID_TRIGGER; flag.velocity = '0 0 0'; flag.angles = flag.mangle; @@ -546,6 +567,9 @@ void ctf_FlagSetup(float teamnumber, entity flag) // called when spawning a flag flag.solid = SOLID_TRIGGER; flag.takedamage = DAMAGE_NO; flag.damageforcescale = autocvar_g_ctf_flag_damageforcescale; + flag.max_flag_health = ((autocvar_g_ctf_flag_take_damage && autocvar_g_ctf_flag_health) ? autocvar_g_ctf_flag_health : 100); + flag.health = flag.max_flag_health; + flag.event_damage = ctf_FlagDamage; flag.velocity = '0 0 0'; flag.mangle = flag.angles; flag.reset = ctf_Reset; @@ -575,18 +599,20 @@ void ctf_FlagSetup(float teamnumber, entity flag) // called when spawning a flag if(autocvar_g_ctf_dynamiclights) { flag.effects |= ((teamnumber) ? EF_RED : EF_BLUE); } // sound - if(!flag.noise) { flag.noise = ((teamnumber) ? "ctf/red_taken.wav" : "ctf/blue_taken.wav"); } - if(!flag.noise1) { flag.noise1 = ((teamnumber) ? "ctf/red_returned.wav" : "ctf/blue_returned.wav"); } - if(!flag.noise2) { flag.noise2 = ((teamnumber) ? "ctf/red_capture.wav" : "ctf/blue_capture.wav"); } // blue team scores by capturing the red flag - if(!flag.noise3) { flag.noise3 = "ctf/flag_respawn.wav"; } // if there is ever a team-based sound for this, update the code to match. - if(!flag.noise4) { flag.noise4 = ((teamnumber) ? "ctf/red_dropped.wav" : "ctf/blue_dropped.wav"); } + if(!flag.snd_flag_taken) { flag.snd_flag_taken = ((teamnumber) ? "ctf/red_taken.wav" : "ctf/blue_taken.wav"); } + if(!flag.snd_flag_returned) { flag.snd_flag_returned = ((teamnumber) ? "ctf/red_returned.wav" : "ctf/blue_returned.wav"); } + if(!flag.snd_flag_capture) { flag.snd_flag_capture = ((teamnumber) ? "ctf/red_capture.wav" : "ctf/blue_capture.wav"); } // blue team scores by capturing the red flag + if(!flag.snd_flag_respawn) { flag.snd_flag_respawn = "ctf/flag_respawn.wav"; } // if there is ever a team-based sound for this, update the code to match. + if(!flag.snd_flag_dropped) { flag.snd_flag_dropped = ((teamnumber) ? "ctf/red_dropped.wav" : "ctf/blue_dropped.wav"); } + if(!flag.snd_flag_touch) { flag.snd_flag_touch = "ctf/flag_touch.wav"; } // again has no team-based sound // precache - precache_sound(flag.noise); - precache_sound(flag.noise1); - precache_sound(flag.noise2); - precache_sound(flag.noise3); - precache_sound(flag.noise4); + precache_sound(flag.snd_flag_taken); + precache_sound(flag.snd_flag_returned); + precache_sound(flag.snd_flag_capture); + precache_sound(flag.snd_flag_respawn); + precache_sound(flag.snd_flag_dropped); + precache_sound(flag.snd_flag_touch); precache_model(flag.model); precache_model("models/ctf/shield.md3"); precache_model("models/ctf/shockwavetransring.md3"); @@ -597,7 +623,6 @@ void ctf_FlagSetup(float teamnumber, entity flag) // called when spawning a flag flag.dropped_origin = flag.origin; flag.noalign = TRUE; flag.movetype = MOVETYPE_NONE; - print("^1|^3||||^1| This map was loaded with flags using MOVETYPE_NONE\n"); } else // drop to floor, automatically find a platform and set that as spawn origin { @@ -605,7 +630,6 @@ void ctf_FlagSetup(float teamnumber, entity flag) // called when spawning a flag self = flag; droptofloor(); flag.movetype = MOVETYPE_TOSS; - print("^1|^3||||^1| This map was loaded with flags using MOVETYPE_TOSS\n"); } InitializeEntity(flag, ctf_DelayedFlagSetup, INITPRIO_SETLOCATION); @@ -646,6 +670,8 @@ MUTATOR_HOOKFUNCTION(ctf_PlayerPreThink) self.items |= ((flag.items & IT_KEY2) ? IT_RED_FLAG_LOST : IT_BLUE_FLAG_LOST); // lost: the flag is dropped somewhere on the map } + if(self.wps_flagcarrier) { WaypointSprite_UpdateHealth(self.wps_flagcarrier, self.health); } + return 0; } @@ -732,14 +758,16 @@ void spawnfunc_info_player_team4() } /*QUAKED spawnfunc_item_flag_team1 (0 0.5 0.8) (-48 -48 -37) (48 48 37) -CTF flag for team one (Red). Multiple flags are allowed. +CTF flag for team one (Red). Keys: "angle" Angle the flag will point (minus 90 degrees)... -"model" model to use, note this needs red and blue as skins 0 and 1 (default models/ctf/flag.md3)... -"noise" sound played when flag is picked up (default ctf/take.wav)... -"noise1" sound played when flag is returned by a teammate (default ctf/return.wav)... -"noise2" sound played when flag is captured (default ctf/redcapture.wav)... -"noise3" sound played when flag is lost in the field and respawns itself (default ctf/respawn.wav)... */ +"model" model to use, note this needs red and blue as skins 0 and 1... +"noise" sound played when flag is picked up... +"noise1" sound played when flag is returned by a teammate... +"noise2" sound played when flag is captured... +"noise3" sound played when flag is lost in the field and respawns itself... +"noise4" sound played when flag is dropped by a player... +"noise5" sound played when flag touches the ground... */ void spawnfunc_item_flag_team1() { if(!g_ctf) { remove(self); return; } @@ -748,14 +776,16 @@ void spawnfunc_item_flag_team1() } /*QUAKED spawnfunc_item_flag_team2 (0 0.5 0.8) (-48 -48 -37) (48 48 37) -CTF flag for team two (Blue). Multiple flags are allowed. +CTF flag for team two (Blue). Keys: "angle" Angle the flag will point (minus 90 degrees)... -"model" model to use, note this needs red and blue as skins 0 and 1 (default models/ctf/flag.md3)... -"noise" sound played when flag is picked up (default ctf/take.wav)... -"noise1" sound played when flag is returned by a teammate (default ctf/return.wav)... -"noise2" sound played when flag is captured (default ctf/redcapture.wav)... -"noise3" sound played when flag is lost in the field and respawns itself (default ctf/respawn.wav)... */ +"model" model to use, note this needs red and blue as skins 0 and 1... +"noise" sound played when flag is picked up... +"noise1" sound played when flag is returned by a teammate... +"noise2" sound played when flag is captured... +"noise3" sound played when flag is lost in the field and respawns itself... +"noise4" sound played when flag is dropped by a player... +"noise5" sound played when flag touches the ground... */ void spawnfunc_item_flag_team2() { if(!g_ctf) { remove(self); return; } diff --git a/qcsrc/server/mutators/gamemode_ctf.qh b/qcsrc/server/mutators/gamemode_ctf.qh index 9f8a65ccc..f171d9635 100644 --- a/qcsrc/server/mutators/gamemode_ctf.qh +++ b/qcsrc/server/mutators/gamemode_ctf.qh @@ -19,6 +19,22 @@ void spawnfunc_ctf_team(); #define FLAG_SPAWN_OFFSET ('0 0 1' * (PL_MAX_z - 13)) #define FLAG_WAYPOINT_OFFSET ('0 0 64') #define FLAG_SCALE 0.6 +#define FLAG_THINKRATE 0.2 + +#define FLAG_BASE 1 +#define FLAG_CARRY 2 +#define FLAG_DROPPED 3 + +// sounds +.string noise4; +.string noise5; + +#define snd_flag_taken noise +#define snd_flag_returned noise1 +#define snd_flag_capture noise2 +#define snd_flag_respawn noise3 +#define snd_flag_dropped noise4 +#define snd_flag_touch noise5 // list of flags on the map entity ctf_worldflaglist; @@ -38,6 +54,7 @@ float ctf_captimerecord; // record time for capturing the flag .float ctf_dropperid; // don't allow spam of dropping the flag .float ctf_droptime; .float ctf_status; // status of the flag (FLAG_BASE, FLAG_DROPPED, FLAG_CARRY declared globally) +.float max_flag_health; // CaptureShield: If the player is too bad to be allowed to capture, shield them from taking the flag. .float ctf_captureshielded; // set to 1 if the player is too bad to be allowed to capture