X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fserver%2Fmutators%2Fmutator%2Fgamemode_ctf.qc;h=51395b86586a0cb50da0246ad533667cc01cd4ce;hp=73e992c95b0d54c862dbd61dd9037a7564ad70d0;hb=64b8409b2d6fb93dc51ba24a82d219c8cd56a907;hpb=ae8867e3301e6cdda736e245858932f8f36d71f1 diff --git a/qcsrc/server/mutators/mutator/gamemode_ctf.qc b/qcsrc/server/mutators/mutator/gamemode_ctf.qc index 73e992c95b..51395b8658 100644 --- a/qcsrc/server/mutators/mutator/gamemode_ctf.qc +++ b/qcsrc/server/mutators/mutator/gamemode_ctf.qc @@ -6,15 +6,15 @@ void ctf_Initialize(); REGISTER_MUTATOR(ctf, false) { - ActivateTeamplay(); - SetLimits(autocvar_capturelimit_override, -1, autocvar_captureleadlimit_override, -1); - have_team_spawns = -1; // request team spawns - MUTATOR_ONADD { if (time > 1) // game loads at time 1 error("This is a game type and it cannot be added at runtime."); ctf_Initialize(); + + ActivateTeamplay(); + SetLimits(autocvar_capturelimit_override, autocvar_captureleadlimit_override, -1, -1); + have_team_spawns = -1; // request team spawns } MUTATOR_ONROLLBACK_OR_REMOVE @@ -47,9 +47,14 @@ const int SP_CTF_DROPS = 7; const int SP_CTF_FCKILLS = 8; const int SP_CTF_RETURNS = 9; +CLASS(Flag, Pickup) + ATTRIB(Flag, m_mins, vector, PL_MIN_CONST + '0 0 -13') + ATTRIB(Flag, m_maxs, vector, PL_MAX_CONST + '0 0 -13') +ENDCLASS(Flag) +Flag CTF_FLAG; STATIC_INIT(Flag) { CTF_FLAG = NEW(Flag); } +void ctf_FlagTouch() { SELFPARAM(); ITEM_HANDLE(Pickup, CTF_FLAG, this, other); } + // flag constants // for most of these, there is just one question to be asked: WHYYYYY? -#define FLAG_MIN (PL_MIN_CONST + '0 0 -13') -#define FLAG_MAX (PL_MAX_CONST + '0 0 -13') const float FLAG_SCALE = 0.6; @@ -125,6 +130,8 @@ const int RETURN_DAMAGE = 3; const int RETURN_SPEEDRUN = 4; const int RETURN_NEEDKILL = 5; +void ctf_Handle_Throw(entity player, entity receiver, float droptype); + // flag properties #define ctf_spawnorigin dropped_origin bool ctf_stalemate; // indicates that a stalemate is active @@ -176,7 +183,7 @@ void havocbot_role_ctf_setrole(entity bot, int role); #define CTF_DIFFTEAM(a,b) ((autocvar_g_ctf_reverse || (ctf_oneflag && autocvar_g_ctf_oneflag_reverse)) ? SAME_TEAM(a,b) : DIFF_TEAM(a,b)) // networked flag statuses -.int ctf_flagstatus; +.int ctf_flagstatus = _STAT(CTF_FLAGSTATUS); #endif const int CTF_RED_FLAG_TAKEN = 1; @@ -242,6 +249,7 @@ bool autocvar_g_ctf_flag_dropped_floatinwater; bool autocvar_g_ctf_flag_glowtrails; int autocvar_g_ctf_flag_health; bool autocvar_g_ctf_flag_return; +bool autocvar_g_ctf_flag_return_carrying; float autocvar_g_ctf_flag_return_carried_radius; float autocvar_g_ctf_flag_return_time; bool autocvar_g_ctf_flag_return_when_unreachable; @@ -467,13 +475,12 @@ void ctf_CaptureShield_Touch() void ctf_CaptureShield_Spawn(entity flag) {SELFPARAM(); - entity shield = spawn(); + entity shield = new(ctf_captureshield); 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; @@ -672,6 +679,10 @@ void ctf_Handle_Throw(entity player, entity receiver, int droptype) ctf_CaptureShield_Update(player, 0); // shield player from picking up flag } +void shockwave_spawn(string m, vector org, float sz, float t1, float t2) +{ + return modeleffect_spawn(m, 0, 0, org, '0 0 0', '0 0 0', '0 0 0', 0, sz, 1, t1, t2); +} // ============== // Event Handlers @@ -930,7 +941,7 @@ bool ctf_Stalemate_Customize() return true; } -void ctf_CheckStalemate(void) +void ctf_CheckStalemate() { // declarations int stale_flags = 0, stale_red_flags = 0, stale_blue_flags = 0, stale_yellow_flags = 0, stale_pink_flags = 0, stale_neutral_flags = 0; @@ -1033,11 +1044,11 @@ void ctf_FlagThink() ctf_CaptureShield_Update(tmp_entity, 1); // release shield only // sanity checks - if(self.mins != FLAG_MIN || self.maxs != FLAG_MAX) { // reset the flag boundaries in case it got squished + if(self.mins != CTF_FLAG.m_mins || self.maxs != CTF_FLAG.m_maxs) { // reset the flag boundaries in case it got squished LOG_TRACE("wtf the flag got squashed?\n"); - tracebox(self.origin, FLAG_MIN, FLAG_MAX, self.origin, MOVE_NOMONSTERS, self); + tracebox(self.origin, CTF_FLAG.m_mins, CTF_FLAG.m_maxs, self.origin, MOVE_NOMONSTERS, self); if(!trace_startsolid || self.noalign) // can we resize it without getting stuck? - setsize(self, FLAG_MIN, FLAG_MAX); } + setsize(self, CTF_FLAG.m_mins, CTF_FLAG.m_maxs); } switch(self.ctf_status) // reset flag angles in case warpzones adjust it { @@ -1114,8 +1125,8 @@ void ctf_FlagThink() ctf_CheckFlagReturn(self, RETURN_SPEEDRUN); setself(self.owner); - self.impulse = CHIMPULSE_SPEEDRUN; // move the player back to the waypoint they set - ImpulseCommands(); + self.impulse = CHIMPULSE_SPEEDRUN.impulse; // move the player back to the waypoint they set + ImpulseCommands(self); setself(this); } if(autocvar_g_ctf_stalemate) @@ -1168,26 +1179,27 @@ void ctf_FlagThink() } } -void ctf_FlagTouch() -{SELFPARAM(); +METHOD(Flag, giveTo, bool(Flag this, entity flag, entity toucher)) +{ + return = false; if(gameover) { return; } if(trace_dphitcontents & (DPCONTENTS_PLAYERCLIP | DPCONTENTS_MONSTERCLIP)) { return; } - entity toucher = other, tmp_entity; - bool is_not_monster = (!IS_MONSTER(toucher)), num_perteam = 0; + bool is_not_monster = (!IS_MONSTER(toucher)); // automatically kill the flag and return it if it touched lava/slime/nodrop surfaces if(ITEM_TOUCH_NEEDKILL()) { if(!autocvar_g_ctf_flag_return_damage_delay) { - self.health = 0; - ctf_CheckFlagReturn(self, RETURN_NEEDKILL); + flag.health = 0; + ctf_CheckFlagReturn(flag, RETURN_NEEDKILL); } - if(!self.ctf_flagdamaged) { return; } + if(!flag.ctf_flagdamaged) { return; } } - FOR_EACH_PLAYER(tmp_entity) if(SAME_TEAM(toucher, tmp_entity)) { ++num_perteam; } + int num_perteam = 0; + entity tmp_entity; FOR_EACH_PLAYER(tmp_entity) if(SAME_TEAM(toucher, tmp_entity)) { ++num_perteam; } // special touch behaviors if(toucher.frozen) { return; } @@ -1205,40 +1217,45 @@ void ctf_FlagTouch() } else if (!IS_PLAYER(toucher)) // The flag just touched an object, most likely the world { - if(time > self.wait) // if we haven't in a while, play a sound/effect + if(time > flag.wait) // if we haven't in a while, play a sound/effect { - Send_Effect_(self.toucheffect, self.origin, '0 0 0', 1); - _sound(self, CH_TRIGGER, self.snd_flag_touch, VOL_BASE, ATTEN_NORM); - self.wait = time + FLAG_TOUCHRATE; + Send_Effect_(flag.toucheffect, flag.origin, '0 0 0', 1); + _sound(flag, CH_TRIGGER, flag.snd_flag_touch, VOL_BASE, ATTEN_NORM); + flag.wait = time + FLAG_TOUCHRATE; } return; } else if(toucher.deadflag != DEAD_NO) { return; } - switch(self.ctf_status) + switch(flag.ctf_status) { case FLAG_BASE: { if(ctf_oneflag) { - if(CTF_SAMETEAM(toucher, self) && (toucher.flagcarried) && !toucher.flagcarried.team && is_not_monster) - ctf_Handle_Capture(self, toucher, CAPTURE_NORMAL); // toucher just captured the neutral flag to enemy base - else if(!self.team && (!toucher.flagcarried) && (!toucher.ctf_captureshielded) && (time > toucher.next_take_time) && is_not_monster) - ctf_Handle_Pickup(self, toucher, PICKUP_BASE); // toucher just stole the neutral flag + if(CTF_SAMETEAM(toucher, flag) && (toucher.flagcarried) && !toucher.flagcarried.team && is_not_monster) + ctf_Handle_Capture(flag, toucher, CAPTURE_NORMAL); // toucher just captured the neutral flag to enemy base + else if(!flag.team && (!toucher.flagcarried) && (!toucher.ctf_captureshielded) && (time > toucher.next_take_time) && is_not_monster) + ctf_Handle_Pickup(flag, toucher, PICKUP_BASE); // toucher just stole the neutral flag + } + else if(CTF_SAMETEAM(toucher, flag) && (toucher.flagcarried) && DIFF_TEAM(toucher.flagcarried, flag) && is_not_monster) + ctf_Handle_Capture(flag, toucher, CAPTURE_NORMAL); // toucher just captured the enemies flag to his base + else if(CTF_DIFFTEAM(toucher, flag) && (toucher.flagcarried) && CTF_SAMETEAM(toucher.flagcarried, toucher) && (!toucher.ctf_captureshielded) && autocvar_g_ctf_flag_return_carrying && (time > toucher.next_take_time) && is_not_monster) + { + ctf_Handle_Return(toucher.flagcarried, toucher); // return their current flag + ctf_Handle_Pickup(flag, toucher, PICKUP_BASE); // now pickup the flag } - else if(CTF_SAMETEAM(toucher, self) && (toucher.flagcarried) && DIFF_TEAM(toucher.flagcarried, self) && is_not_monster) - ctf_Handle_Capture(self, toucher, CAPTURE_NORMAL); // toucher just captured the enemies flag to his base - else if(CTF_DIFFTEAM(toucher, self) && (!toucher.flagcarried) && (!toucher.ctf_captureshielded) && (time > toucher.next_take_time) && is_not_monster) - ctf_Handle_Pickup(self, toucher, PICKUP_BASE); // toucher just stole the enemies flag + else if(CTF_DIFFTEAM(toucher, flag) && (!toucher.flagcarried) && (!toucher.ctf_captureshielded) && (time > toucher.next_take_time) && is_not_monster) + ctf_Handle_Pickup(flag, toucher, PICKUP_BASE); // toucher just stole the enemies flag break; } case FLAG_DROPPED: { - if(CTF_SAMETEAM(toucher, self) && (autocvar_g_ctf_flag_return || num_perteam <= 1) && self.team) // automatically return if there's only 1 player on the team - ctf_Handle_Return(self, toucher); // toucher just returned his own flag - else if(is_not_monster && (!toucher.flagcarried) && ((toucher != self.ctf_dropper) || (time > self.ctf_droptime + autocvar_g_ctf_flag_collect_delay))) - ctf_Handle_Pickup(self, toucher, PICKUP_DROPPED); // toucher just picked up a dropped enemy flag + if(CTF_SAMETEAM(toucher, flag) && (autocvar_g_ctf_flag_return || num_perteam <= 1 || (autocvar_g_ctf_flag_return_carrying && toucher.flagcarried)) && flag.team) // automatically return if there's only 1 player on the team + ctf_Handle_Return(flag, toucher); // toucher just returned his own flag + else if(is_not_monster && (!toucher.flagcarried) && ((toucher != flag.ctf_dropper) || (time > flag.ctf_droptime + autocvar_g_ctf_flag_collect_delay))) + ctf_Handle_Pickup(flag, toucher, PICKUP_DROPPED); // toucher just picked up a dropped enemy flag break; } @@ -1250,12 +1267,12 @@ void ctf_FlagTouch() case FLAG_PASSING: { - if((IS_PLAYER(toucher)) && (toucher.deadflag == DEAD_NO) && (toucher != self.pass_sender)) + if((IS_PLAYER(toucher)) && (toucher.deadflag == DEAD_NO) && (toucher != flag.pass_sender)) { - if(DIFF_TEAM(toucher, self.pass_sender)) - ctf_Handle_Return(self, toucher); + if(DIFF_TEAM(toucher, flag.pass_sender)) + ctf_Handle_Return(flag, toucher); else - ctf_Handle_Retrieve(self, toucher); + ctf_Handle_Retrieve(flag, toucher); } break; } @@ -1314,16 +1331,15 @@ void ctf_RespawnFlag(entity flag) ctf_CheckStalemate(); } -void ctf_Reset() -{SELFPARAM(); - if(self.owner) - if(IS_PLAYER(self.owner)) - ctf_Handle_Throw(self.owner, world, DROP_RESET); +void ctf_Reset(entity this) +{ + if(this.owner && IS_PLAYER(this.owner)) + ctf_Handle_Throw(this.owner, world, DROP_RESET); - ctf_RespawnFlag(self); + ctf_RespawnFlag(this); } -void ctf_DelayedFlagSetup(void) // called after a flag is placed on a map by ctf_FlagSetup() +void ctf_DelayedFlagSetup() // called after a flag is placed on a map by ctf_FlagSetup() {SELFPARAM(); // bot waypoints waypoint_spawnforitem_force(self, self.origin); @@ -1349,12 +1365,6 @@ void ctf_DelayedFlagSetup(void) // called after a flag is placed on a map by ctf ctf_CaptureShield_Spawn(self); } -void set_flag_string(entity flag, .string field, string value, string teamname) -{ - if(flag.(field) == "") - flag.(field) = strzone(sprintf(value,teamname)); -} - void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag entity on the map as a spawnfunc {SELFPARAM(); // declarations @@ -1395,20 +1405,20 @@ void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag e if(!flag.scale) { flag.scale = FLAG_SCALE; } if(flag.skin == 0) { flag.skin = cvar(sprintf("g_ctf_flag_%s_skin", teamname)); } if(flag.model == "") { flag.model = cvar_string(sprintf("g_ctf_flag_%s_model", teamname)); } - set_flag_string(flag, toucheffect, "%sflag_touch", teamname); - set_flag_string(flag, passeffect, "%s_pass", teamname); - set_flag_string(flag, capeffect, "%s_cap", teamname); + if (flag.toucheffect == "") { flag.toucheffect = EFFECT_FLAG_TOUCH(teamnumber).eent_eff_name; } + if (flag.passeffect == "") { flag.passeffect = EFFECT_PASS(teamnumber).eent_eff_name; } + if (flag.capeffect == "") { flag.capeffect = EFFECT_CAP(teamnumber).eent_eff_name; } // sounds - flag.snd_flag_taken = SND(CTF_TAKEN(teamnumber)); - flag.snd_flag_returned = SND(CTF_RETURNED(teamnumber)); - flag.snd_flag_capture = SND(CTF_CAPTURE(teamnumber)); - flag.snd_flag_dropped = SND(CTF_DROPPED(teamnumber)); - if (flag.snd_flag_respawn == "") flag.snd_flag_respawn = SND(CTF_RESPAWN); // if there is ever a team-based sound for this, update the code to match. + flag.snd_flag_taken = strzone(SND(CTF_TAKEN(teamnumber))); + flag.snd_flag_returned = strzone(SND(CTF_RETURNED(teamnumber))); + flag.snd_flag_capture = strzone(SND(CTF_CAPTURE(teamnumber))); + flag.snd_flag_dropped = strzone(SND(CTF_DROPPED(teamnumber))); + if (flag.snd_flag_respawn == "") flag.snd_flag_respawn = strzone(SND(CTF_RESPAWN)); // if there is ever a team-based sound for this, update the code to match. precache_sound(flag.snd_flag_respawn); - if (flag.snd_flag_touch == "") flag.snd_flag_touch = SND(CTF_TOUCH); // again has no team-based sound + if (flag.snd_flag_touch == "") flag.snd_flag_touch = strzone(SND(CTF_TOUCH)); // again has no team-based sound precache_sound(flag.snd_flag_touch); - if (flag.snd_flag_pass == "") flag.snd_flag_pass = SND(CTF_PASS); // same story here + if (flag.snd_flag_pass == "") flag.snd_flag_pass = strzone(SND(CTF_PASS)); // same story here precache_sound(flag.snd_flag_pass); // precache @@ -1416,7 +1426,7 @@ void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag e // appearence _setmodel(flag, flag.model); // precision set below - setsize(flag, FLAG_MIN, FLAG_MAX); + setsize(flag, CTF_FLAG.m_mins, CTF_FLAG.m_maxs); setorigin(flag, (flag.origin + FLAG_SPAWN_OFFSET)); if(autocvar_g_ctf_flag_glowtrails) @@ -2749,7 +2759,7 @@ void ctf_DelayedInit() // Do this check with a delay so we can wait for teams to // if no teams are found, spawn defaults if(find(world, classname, "ctf_team") == world) { - LOG_INFO("No ""ctf_team"" entities found on this map, creating them anyway.\n"); + LOG_INFO("No \"ctf_team\" entities found on this map, creating them anyway.\n"); ctf_SpawnTeam("Red", NUM_TEAM_1 - 1); ctf_SpawnTeam("Blue", NUM_TEAM_2 - 1); if(ctf_teams >= 3) @@ -2769,8 +2779,6 @@ void ctf_Initialize() ctf_captureshield_max_ratio = autocvar_g_ctf_shield_max_ratio; ctf_captureshield_force = autocvar_g_ctf_shield_force; - addstat(STAT_CTF_FLAGSTATUS, AS_INT, ctf_flagstatus); - InitializeEntity(world, ctf_DelayedInit, INITPRIO_GAMETYPE); }