#include <common/effects/all.qh>
#include <common/mapobjects/teleporters.qh>
#include <common/mapobjects/triggers.qh>
+#include <common/mutators/mutator/powerups/_mod.qh>
#include <common/vehicles/all.qh>
#include <server/command/vote.qh>
#include <server/client.qh>
flag.angles = '0 0 0';
SetResourceExplicit(flag, RES_HEALTH, flag.max_health);
flag.ctf_droptime = time;
+ flag.ctf_landtime = 0;
flag.ctf_dropper = player;
flag.ctf_status = FLAG_DROPPED;
flag.solid = SOLID_TRIGGER;
flag.ctf_dropper = player;
flag.ctf_droptime = time;
+ flag.ctf_landtime = 0;
flag.flags = FL_ITEM | FL_NOTARGET; // clear FL_ONGROUND for MOVETYPE_TOSS
{
makevectors((player.v_angle.y * '0 1 0') + (bound(autocvar_g_ctf_throw_angle_min, player.v_angle.x, autocvar_g_ctf_throw_angle_max) * '1 0 0'));
- flag_velocity = (('0 0 1' * autocvar_g_ctf_throw_velocity_up) + ((v_forward * autocvar_g_ctf_throw_velocity_forward) * ((player.items & ITEM_Strength.m_itemid) ? autocvar_g_ctf_throw_strengthmultiplier : 1)));
+ flag_velocity = (('0 0 1' * autocvar_g_ctf_throw_velocity_up) + ((v_forward * autocvar_g_ctf_throw_velocity_forward) * ((StatusEffects_active(STATUSEFFECT_Strength, player)) ? autocvar_g_ctf_throw_strengthmultiplier : 1)));
flag.velocity = W_CalculateProjectileVelocity(player, player.velocity, flag_velocity, false);
ctf_Handle_Drop(flag, player, droptype);
navigation_dynamicgoal_set(flag, player);
for(tmp_entity = ctf_worldflaglist; tmp_entity; tmp_entity = tmp_entity.ctf_worldflagnext)
if(tmp_entity.ctf_status == FLAG_DROPPED)
if(vdist(this.origin - tmp_entity.origin, <, autocvar_g_ctf_dropped_capture_radius))
- if(time > tmp_entity.ctf_droptime + autocvar_g_ctf_dropped_capture_delay)
+ if((this.noalign || tmp_entity.ctf_landtime) && time > ((this.noalign) ? tmp_entity.ctf_droptime : tmp_entity.ctf_landtime) + autocvar_g_ctf_dropped_capture_delay)
ctf_Handle_Capture(this, tmp_entity, CAPTURE_DROPPED);
}
return;
case FLAG_DROPPED:
{
this.angles = '0 0 0'; // reset flag angles in case warpzones adjust it
+ if(IS_ONGROUND(this) && !this.ctf_landtime)
+ this.ctf_landtime = time; // landtime is reset when thrown, and we don't want to restart the timer if the flag is pushed
if(autocvar_g_ctf_flag_dropped_floatinwater)
{
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
+ ctf_Handle_Capture(flag, toucher, CAPTURE_NORMAL); // toucher just captured the enemies flag to their 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
case FLAG_DROPPED:
{
if(CTF_SAMETEAM(toucher, flag) && ctf_Immediate_Return_Allowed(flag, toucher))
- ctf_Handle_Return(flag, toucher); // toucher just returned his own flag
+ ctf_Handle_Return(flag, toucher); // toucher just returned their 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;
flag.ctf_dropper = NULL;
flag.ctf_pickuptime = 0;
flag.ctf_droptime = 0;
+ flag.ctf_landtime = 0;
flag.ctf_flagdamaged_byworld = false;
navigation_dynamicgoal_unset(flag);
{
if (head.ctf_status == FLAG_CARRY)
{
- // adjust rating of our flag carrier depending on his health
+ // adjust rating of our flag carrier depending on their health
head = head.tag_entity;
float f = bound(0, (GetResource(head, RES_HEALTH) + GetResource(head, RES_ARMOR)) / 100, 2) - 1;
ratingscale += ratingscale * f * 0.1;
entity goal = this.goalentity;
if (havocbot_ctf_is_basewaypoint(goal) && vdist(goal.origin - this.origin, <, 100))
- this.goalentity_lock_timeout = time + ((this.bot_aimtarg) ? 2 : 3);
+ this.goalentity_lock_timeout = time + ((this.enemy) ? 2 : 3);
if (goal)
this.havocbot_cantfindflag = time + 10;
bool b1 = false, b2 = false, b3 = false, b4 = false, b5 = false; // TODO: kill this, we WANT to show the other flags, somehow! (note: also means you don't see if you're FC)
// initially clear items so they can be set as necessary later.
- STAT(CTF_FLAGSTATUS, player) &= ~(CTF_RED_FLAG_CARRYING | CTF_RED_FLAG_TAKEN | CTF_RED_FLAG_LOST
+ STAT(OBJECTIVE_STATUS, player) &= ~(CTF_RED_FLAG_CARRYING | CTF_RED_FLAG_TAKEN | CTF_RED_FLAG_LOST
| CTF_BLUE_FLAG_CARRYING | CTF_BLUE_FLAG_TAKEN | CTF_BLUE_FLAG_LOST
| CTF_YELLOW_FLAG_CARRYING | CTF_YELLOW_FLAG_TAKEN | CTF_YELLOW_FLAG_LOST
| CTF_PINK_FLAG_CARRYING | CTF_PINK_FLAG_TAKEN | CTF_PINK_FLAG_LOST
if(flag.team == NUM_TEAM_2 && !b2) { b2 = true; t = CTF_BLUE_FLAG_CARRYING; t2 = CTF_BLUE_FLAG_TAKEN; t3 = CTF_BLUE_FLAG_LOST; }
if(flag.team == NUM_TEAM_3 && !b3) { b3 = true; t = CTF_YELLOW_FLAG_CARRYING; t2 = CTF_YELLOW_FLAG_TAKEN; t3 = CTF_YELLOW_FLAG_LOST; }
if(flag.team == NUM_TEAM_4 && !b4) { b4 = true; t = CTF_PINK_FLAG_CARRYING; t2 = CTF_PINK_FLAG_TAKEN; t3 = CTF_PINK_FLAG_LOST; }
- if(flag.team == 0 && !b5) { b5 = true; t = CTF_NEUTRAL_FLAG_CARRYING; t2 = CTF_NEUTRAL_FLAG_TAKEN; t3 = CTF_NEUTRAL_FLAG_LOST; STAT(CTF_FLAGSTATUS, player) |= CTF_FLAG_NEUTRAL; }
+ if(flag.team == 0 && !b5) { b5 = true; t = CTF_NEUTRAL_FLAG_CARRYING; t2 = CTF_NEUTRAL_FLAG_TAKEN; t3 = CTF_NEUTRAL_FLAG_LOST; STAT(OBJECTIVE_STATUS, player) |= CTF_FLAG_NEUTRAL; }
switch(flag.ctf_status)
{
case FLAG_CARRY:
{
if((flag.owner == player) || (flag.pass_sender == player))
- STAT(CTF_FLAGSTATUS, player) |= t; // carrying: player is currently carrying the flag
+ STAT(OBJECTIVE_STATUS, player) |= t; // carrying: player is currently carrying the flag
else
- STAT(CTF_FLAGSTATUS, player) |= t2; // taken: someone else is carrying the flag
+ STAT(OBJECTIVE_STATUS, player) |= t2; // taken: someone else is carrying the flag
break;
}
case FLAG_DROPPED:
{
- STAT(CTF_FLAGSTATUS, player) |= t3; // lost: the flag is dropped somewhere on the map
+ STAT(OBJECTIVE_STATUS, player) |= t3; // lost: the flag is dropped somewhere on the map
break;
}
}
// item for stopping players from capturing the flag too often
if(player.ctf_captureshielded)
- STAT(CTF_FLAGSTATUS, player) |= CTF_SHIELDED;
+ STAT(OBJECTIVE_STATUS, player) |= CTF_SHIELDED;
if(ctf_stalemate)
- STAT(CTF_FLAGSTATUS, player) |= CTF_STALEMATE;
+ STAT(OBJECTIVE_STATUS, player) |= CTF_STALEMATE;
// update the health of the flag carrier waypointsprite
if(player.wps_flagcarrier)
entity player = M_ARGV(0, entity);
- if(IS_REAL_CLIENT(player))
- {
- int m = min(RANKINGS_CNT, autocvar_g_cts_send_rankings_cnt);
- race_send_rankings_cnt(MSG_ONE);
- for (int i = 1; i <= m; ++i)
- {
- race_SendRankings(i, 0, 0, MSG_ONE);
- }
- }
+ race_SendAll(player, true);
}
MUTATOR_HOOKFUNCTION(ctf, GetPressedKeys)
entity player = M_ARGV(0, entity);
- if(CS(player).cvar_cl_allow_uidtracking == 1 && CS(player).cvar_cl_allow_uid2name == 1)
- {
- if (!player.stored_netname)
- player.stored_netname = strzone(uid2name(player.crypto_idfp));
- if(player.stored_netname != player.netname)
- {
- db_put(ServerProgsDB, strcat("/uid2name/", player.crypto_idfp), player.netname);
- strcpy(player.stored_netname, player.netname);
- }
- }
+ race_checkAndWriteName(player);
}
MUTATOR_HOOKFUNCTION(ctf, PortalTeleport)
M_ARGV(1, string) = "ctf_team";
}
-MUTATOR_HOOKFUNCTION(ctf, SpectateCopy)
-{
- entity spectatee = M_ARGV(0, entity);
- entity client = M_ARGV(1, entity);
-
- STAT(CTF_FLAGSTATUS, client) = STAT(CTF_FLAGSTATUS, spectatee);
-}
-
MUTATOR_HOOKFUNCTION(ctf, GetRecords)
{
int record_page = M_ARGV(0, int);
void ctf_Initialize()
{
+ CTF_FLAG = NEW(Flag);
+ record_type = CTF_RECORD;
ctf_captimerecord = stof(db_get(ServerProgsDB, strcat(GetMapname(), "/captimerecord/time")));
ctf_captureshield_min_negscore = autocvar_g_ctf_shield_min_negscore;