#include "gamemode_keyhunt.qh"
-#ifndef GAMEMODE_KEYHUNT_H
-#define GAMEMODE_KEYHUNT_H
-
-#define autocvar_g_keyhunt_point_limit cvar("g_keyhunt_point_limit")
-int autocvar_g_keyhunt_point_leadlimit;
-bool autocvar_g_keyhunt_team_spawns;
-void kh_Initialize();
-
-REGISTER_MUTATOR(kh, false)
-{
- MUTATOR_ONADD
- {
- if (time > 1) // game loads at time 1
- error("This is a game type and it cannot be added at runtime.");
- kh_Initialize();
-
- ActivateTeamplay();
- SetLimits(autocvar_g_keyhunt_point_limit, autocvar_g_keyhunt_point_leadlimit, autocvar_timelimit_override, -1);
- if (autocvar_g_keyhunt_team_spawns)
- have_team_spawns = -1; // request team spawns
- }
-
- MUTATOR_ONROLLBACK_OR_REMOVE
- {
- // we actually cannot roll back kh_Initialize here
- // BUT: we don't need to! If this gets called, adding always
- // succeeds.
- }
-
- MUTATOR_ONREMOVE
- {
- LOG_INFO("This is a game type and it cannot be removed at runtime.");
- return -1;
- }
-
- return 0;
-}
-
-#define FOR_EACH_KH_KEY(v) for(v = kh_worldkeylist; v; v = v.kh_worldkeynext )
-
-// ALL OF THESE should be removed in the future, as other code should not have to care
-
-// used by bots:
-float kh_tracking_enabled;
-.entity kh_next;
-float kh_Key_AllOwnedByWhichTeam();
-
-USING(kh_Think_t, void());
-void kh_StartRound();
-void kh_Controller_SetThink(float t, kh_Think_t func);
-
-#endif
-
-#ifdef IMPLEMENTATION
float autocvar_g_balance_keyhunt_damageforcescale;
float autocvar_g_balance_keyhunt_delay_collect;
int autocvar_g_balance_keyhunt_score_push;
float autocvar_g_balance_keyhunt_throwvelocity;
-int autocvar_g_keyhunt_teams;
+//int autocvar_g_keyhunt_teams;
int autocvar_g_keyhunt_teams_override;
// #define KH_PLAYER_USE_ATTACHMENT
const vector KH_KEY_MAX = '10 10 3';
const float KH_KEY_BRIGHTNESS = 2;
-float kh_no_radar_circles;
+bool kh_no_radar_circles;
// kh_state
// bits 0- 4: team of key 1, or 0 for no such key, or 30 for dropped, or 31 for self
.float kh_dropperteam;
.entity kh_previous_owner;
.float kh_previous_owner_playerid;
-.float kh_cp_duration;
float kh_key_dropped, kh_key_carried;
+int kh_Key_AllOwnedByWhichTeam();
+
const float ST_KH_CAPS = 1;
void kh_ScoreRules(int teams)
{
key.angles_y -= key.owner.angles.y;
#endif
key.flags = 0;
+ IL_REMOVE(g_items, key);
key.solid = SOLID_NOT;
set_movetype(key, MOVETYPE_NONE);
key.team = key.owner.team;
key.angles_y += key.owner.angles.y;
#endif
key.flags = FL_ITEM;
+ IL_PUSH(g_items, key);
key.solid = SOLID_TRIGGER;
set_movetype(key, MOVETYPE_TOSS);
key.pain_finished = time + autocvar_g_balance_keyhunt_delay_return;
// immediately return is bad
// maybe start a shorter countdown?
}
- if(vlen(force) <= 0)
+ if(force == '0 0 0')
return;
if(time > this.pushltime)
if(IS_PLAYER(attacker))
PlayerScore_Add(player, SP_KH_PICKUPS, 1);
}
key.kh_dropperteam = 0;
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_ENT(key, INFO_KEYHUNT_PICKUP), player.netname);
+ int realteam = kh_Team_ByID(key.count);
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(realteam, INFO_KEYHUNT_PICKUP), player.netname);
kh_Key_AssignTo(key, player); // this also updates .kh_state
}
kh_Controller_SetThink(autocvar_g_balance_keyhunt_delay_round, kh_StartRound);
}
+void nades_GiveBonus(entity player, float score);
+
void kh_WinnerTeam(float teem) // runs when a team wins // Samual: Teem?.... TEEM?!?! what the fuck is wrong with you people
{
// all key carriers get some points
float first;
entity key;
float score;
- score = (kh_teams - 1) * autocvar_g_balance_keyhunt_score_capture;
- DistributeEvenly_Init(score, kh_teams);
+ score = (NumTeams(kh_teams) - 1) * autocvar_g_balance_keyhunt_score_capture;
+ DistributeEvenly_Init(score, NumTeams(kh_teams));
// twice the score for 3 team games, three times the score for 4 team games!
// note: for a win by destroying the key, this should NOT be applied
FOR_EACH_KH_KEY(key)
firstorigin = thisorigin;
first = false;
}
- if(kh_teams > 2)
+ if(NumTeams(kh_teams) > 2)
{
te_lightning2(NULL, lastorigin, firstorigin);
}
- midpoint = midpoint * (1 / kh_teams);
+ midpoint = midpoint * (1 / NumTeams(kh_teams));
te_customflash(midpoint, 1000, 1, Team_ColorRGB(teem) * 0.5 + '0.5 0.5 0.5'); // make the color >=0.5 in each component
play2all(SND(KH_CAPTURE));
fragsleft = DistributeEvenly_Get(players);
// Now distribute these among all other teams...
- j = kh_teams - 1;
- for(i = 0; i < kh_teams; ++i)
+ j = NumTeams(kh_teams) - 1;
+ for(i = 0; i < NumTeams(kh_teams); ++i)
{
thisteam = kh_Team_ByID(i);
if(thisteam == teem) // bad boy, no cookie - this WILL happen
}
}
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_ENT(lostkey, INFO_KEYHUNT_LOST), lostkey.kh_previous_owner.netname);
+ int realteam = kh_Team_ByID(lostkey.count);
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(realteam, INFO_KEYHUNT_LOST), lostkey.kh_previous_owner.netname);
play2all(SND(KH_DESTROY));
te_tarexplosion(lostkey.origin);
}
// -1 when no team completely owns all keys yet
-float kh_Key_AllOwnedByWhichTeam() // constantly called. check to see if all the keys are owned by the same team
+int kh_Key_AllOwnedByWhichTeam() // constantly called. check to see if all the keys are owned by the same team
{
entity key;
- float teem;
- float keys;
-
- teem = -1;
- keys = kh_teams;
+ int teem = -1;
+ int keys = NumTeams(kh_teams);
FOR_EACH_KH_KEY(key)
{
if(!key.owner)
kh_Scores_Event(player, key, "dropkey", 0, 0);
PlayerScore_Add(player, SP_KH_LOSSES, 1);
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_ENT(key, INFO_KEYHUNT_DROP), player.netname);
+ int realteam = kh_Team_ByID(key.count);
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(realteam, INFO_KEYHUNT_DROP), player.netname);
kh_Key_AssignTo(key, NULL);
makevectors(player.v_angle);
{
kh_Scores_Event(player, key, "losekey", 0, 0);
PlayerScore_Add(player, SP_KH_LOSSES, 1);
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_ENT(key, INFO_KEYHUNT_LOST), player.netname);
+ int realteam = kh_Team_ByID(key.count);
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(realteam, INFO_KEYHUNT_LOST), player.netname);
kh_Key_AssignTo(key, NULL);
makevectors('-1 0 0' * (45 + 45 * random()) + '0 360 0' * random());
key.velocity = W_CalculateProjectileVelocity(player, player.velocity, autocvar_g_balance_keyhunt_dropvelocity * v_forward, false);
}
}
-float kh_CheckPlayers(float num)
+int kh_GetMissingTeams()
{
- if(num < kh_teams)
+ int missing_teams = 0;
+ for(int i = 0; i < NumTeams(kh_teams); ++i)
{
- float t_team = kh_Team_ByID(num);
- float players = 0;
+ int teem = kh_Team_ByID(i);
+ int players = 0;
FOREACH_CLIENT(IS_PLAYER(it), LAMBDA(
- if(!IS_DEAD(it) && !PHYS_INPUT_BUTTON_CHAT(it) && it.team == t_team)
+ if(!IS_DEAD(it) && !PHYS_INPUT_BUTTON_CHAT(it) && it.team == teem)
++players;
));
-
- if (!players) { return t_team; }
+ if (!players)
+ missing_teams |= pow(2, i);
}
- return 0;
+ return missing_teams;
}
-#define KH_READY_TEAMS() (!p1 + !p2 + ((kh_teams >= 3) ? !p3 : p3) + ((kh_teams >= 4) ? !p4 : p4))
-#define KH_READY_TEAMS_OK() (KH_READY_TEAMS() == kh_teams)
void kh_WaitForPlayers() // delay start of the round until enough players are present
{
if(time < game_starttime)
return;
}
- static float prev_missing_teams_mask;
- float p1 = kh_CheckPlayers(0), p2 = kh_CheckPlayers(1), p3 = kh_CheckPlayers(2), p4 = kh_CheckPlayers(3);
- if(KH_READY_TEAMS_OK())
+ static int prev_missing_teams_mask;
+ int missing_teams_mask = kh_GetMissingTeams();
+ if(!missing_teams_mask)
{
if(prev_missing_teams_mask > 0)
Kill_Notification(NOTIF_ALL, NULL, MSG_CENTER, CPID_MISSING_TEAMS);
}
else
{
- int missing_teams_mask = 0;
- if(kh_teams & BIT(0))
- missing_teams_mask += boolean(p1) * 1;
- if(kh_teams & BIT(1))
- missing_teams_mask += boolean(p2) * 2;
- if(kh_teams & BIT(2))
- missing_teams_mask += boolean(p3) * 4;
- if(kh_teams & BIT(3))
- missing_teams_mask += boolean(p4) * 8;
if(prev_missing_teams_mask != missing_teams_mask)
{
Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_MISSING_TEAMS, missing_teams_mask);
void kh_StartRound() // runs at the start of each round
{
- float i, players, teem;
+ int i, players, teem;
if(time < game_starttime)
{
return;
}
- float p1 = kh_CheckPlayers(0), p2 = kh_CheckPlayers(1), p3 = kh_CheckPlayers(2), p4 = kh_CheckPlayers(3);
- if(!KH_READY_TEAMS_OK())
+ if(kh_GetMissingTeams())
{
kh_Controller_SetThink(1, kh_WaitForPlayers);
return;
Kill_Notification(NOTIF_ALL, NULL, MSG_CENTER, CPID_KEYHUNT);
Kill_Notification(NOTIF_ALL, NULL, MSG_CENTER, CPID_KEYHUNT_OTHER);
- for(i = 0; i < kh_teams; ++i)
+ for(i = 0; i < NumTeams(kh_teams); ++i)
{
teem = kh_Team_ByID(i);
players = 0;
my_player = it;
}
));
- kh_Key_Spawn(my_player, 360 * i / kh_teams, i);
+ kh_Key_Spawn(my_player, 360 * i / NumTeams(kh_teams), i);
}
kh_tracking_enabled = false;
// setup variables
kh_teams = autocvar_g_keyhunt_teams_override;
if(kh_teams < 2)
- kh_teams = autocvar_g_keyhunt_teams;
+ kh_teams = cvar("g_keyhunt_teams"); // read the cvar directly as it gets written earlier in the same frame
kh_teams = bound(2, kh_teams, 4);
int teams = 0;
if (!(this.kh_next))
{
- LOG_TRACE("changing role to freelancer\n");
+ LOG_TRACE("changing role to freelancer");
this.havocbot_role = havocbot_role_kh_freelancer;
this.havocbot_role_timeout = 0;
return;
if (this.kh_next)
{
- LOG_TRACE("changing role to carrier\n");
+ LOG_TRACE("changing role to carrier");
this.havocbot_role = havocbot_role_kh_carrier;
this.havocbot_role_timeout = 0;
return;
this.havocbot_role_timeout = time + random() * 10 + 20;
if (time > this.havocbot_role_timeout)
{
- LOG_TRACE("changing role to freelancer\n");
+ LOG_TRACE("changing role to freelancer");
this.havocbot_role = havocbot_role_kh_freelancer;
this.havocbot_role_timeout = 0;
return;
if (this.kh_next)
{
- LOG_TRACE("changing role to carrier\n");
+ LOG_TRACE("changing role to carrier");
this.havocbot_role = havocbot_role_kh_carrier;
this.havocbot_role_timeout = 0;
return;
this.havocbot_role_timeout = time + random() * 10 + 20;
if (time > this.havocbot_role_timeout)
{
- LOG_TRACE("changing role to freelancer\n");
+ LOG_TRACE("changing role to freelancer");
this.havocbot_role = havocbot_role_kh_freelancer;
this.havocbot_role_timeout = 0;
return;
if (this.kh_next)
{
- LOG_TRACE("changing role to carrier\n");
+ LOG_TRACE("changing role to carrier");
this.havocbot_role = havocbot_role_kh_carrier;
this.havocbot_role_timeout = 0;
return;
{
if (random() < 0.5)
{
- LOG_TRACE("changing role to offense\n");
+ LOG_TRACE("changing role to offense");
this.havocbot_role = havocbot_role_kh_offense;
}
else
{
- LOG_TRACE("changing role to defense\n");
+ LOG_TRACE("changing role to defense");
this.havocbot_role = havocbot_role_kh_defense;
}
this.havocbot_role_timeout = 0;
kh_finalize();
}
-MUTATOR_HOOKFUNCTION(kh, GetTeamCount, CBC_ORDER_EXCLUSIVE)
+MUTATOR_HOOKFUNCTION(kh, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
{
M_ARGV(0, float) = kh_teams;
}
{
kh_Controller_SetThink(autocvar_g_balance_keyhunt_delay_round + (game_starttime - time), kh_StartRound);
}
-
-#endif