mirror of
https://github.com/id-Software/quake2-rerelease-dll.git
synced 2026-03-19 16:39:46 +01:00
Initial commit
This commit is contained in:
3832
rerelease/ctf/g_ctf.cpp
Normal file
3832
rerelease/ctf/g_ctf.cpp
Normal file
File diff suppressed because it is too large
Load Diff
162
rerelease/ctf/g_ctf.h
Normal file
162
rerelease/ctf/g_ctf.h
Normal file
@@ -0,0 +1,162 @@
|
||||
// Copyright (c) ZeniMax Media Inc.
|
||||
// Licensed under the GNU General Public License 2.0.
|
||||
|
||||
#define CTF_VERSION 1.52
|
||||
#define CTF_VSTRING2(x) #x
|
||||
#define CTF_VSTRING(x) CTF_VSTRING2(x)
|
||||
#define CTF_STRING_VERSION CTF_VSTRING(CTF_VERSION)
|
||||
|
||||
enum ctfteam_t
|
||||
{
|
||||
CTF_NOTEAM,
|
||||
CTF_TEAM1,
|
||||
CTF_TEAM2
|
||||
};
|
||||
|
||||
enum ctfgrapplestate_t
|
||||
{
|
||||
CTF_GRAPPLE_STATE_FLY,
|
||||
CTF_GRAPPLE_STATE_PULL,
|
||||
CTF_GRAPPLE_STATE_HANG
|
||||
};
|
||||
|
||||
struct ghost_t
|
||||
{
|
||||
char netname[MAX_NETNAME];
|
||||
int number;
|
||||
|
||||
// stats
|
||||
int deaths;
|
||||
int kills;
|
||||
int caps;
|
||||
int basedef;
|
||||
int carrierdef;
|
||||
|
||||
int code; // ghost code
|
||||
ctfteam_t team; // team
|
||||
int score; // frags at time of disconnect
|
||||
edict_t *ent;
|
||||
};
|
||||
|
||||
extern cvar_t *ctf;
|
||||
extern cvar_t *g_teamplay_force_join;
|
||||
extern cvar_t *teamplay;
|
||||
|
||||
constexpr const char *CTF_TEAM1_SKIN = "ctf_r";
|
||||
constexpr const char *CTF_TEAM2_SKIN = "ctf_b";
|
||||
|
||||
constexpr int32_t CTF_CAPTURE_BONUS = 15; // what you get for capture
|
||||
constexpr int32_t CTF_TEAM_BONUS = 10; // what your team gets for capture
|
||||
constexpr int32_t CTF_RECOVERY_BONUS = 1; // what you get for recovery
|
||||
constexpr int32_t CTF_FLAG_BONUS = 0; // what you get for picking up enemy flag
|
||||
constexpr int32_t CTF_FRAG_CARRIER_BONUS = 2; // what you get for fragging enemy flag carrier
|
||||
constexpr gtime_t CTF_FLAG_RETURN_TIME = 40_sec; // seconds until auto return
|
||||
|
||||
constexpr int32_t CTF_CARRIER_DANGER_PROTECT_BONUS = 2; // bonus for fraggin someone who has recently hurt your flag carrier
|
||||
constexpr int32_t CTF_CARRIER_PROTECT_BONUS = 1; // bonus for fraggin someone while either you or your target are near your flag carrier
|
||||
constexpr int32_t CTF_FLAG_DEFENSE_BONUS = 1; // bonus for fraggin someone while either you or your target are near your flag
|
||||
constexpr int32_t CTF_RETURN_FLAG_ASSIST_BONUS = 1; // awarded for returning a flag that causes a capture to happen almost immediately
|
||||
constexpr int32_t CTF_FRAG_CARRIER_ASSIST_BONUS = 2; // award for fragging a flag carrier if a capture happens almost immediately
|
||||
|
||||
constexpr float CTF_TARGET_PROTECT_RADIUS = 400; // the radius around an object being defended where a target will be worth extra frags
|
||||
constexpr float CTF_ATTACKER_PROTECT_RADIUS = 400; // the radius around an object being defended where an attacker will get extra frags when making kills
|
||||
|
||||
constexpr gtime_t CTF_CARRIER_DANGER_PROTECT_TIMEOUT = 8_sec;
|
||||
constexpr gtime_t CTF_FRAG_CARRIER_ASSIST_TIMEOUT = 10_sec;
|
||||
constexpr gtime_t CTF_RETURN_FLAG_ASSIST_TIMEOUT = 10_sec;
|
||||
|
||||
constexpr gtime_t CTF_AUTO_FLAG_RETURN_TIMEOUT = 30_sec; // number of seconds before dropped flag auto-returns
|
||||
|
||||
constexpr gtime_t CTF_TECH_TIMEOUT = 60_sec; // seconds before techs spawn again
|
||||
|
||||
constexpr int32_t CTF_DEFAULT_GRAPPLE_SPEED = 650; // speed of grapple in flight
|
||||
constexpr float CTF_DEFAULT_GRAPPLE_PULL_SPEED = 650; // speed player is pulled at
|
||||
|
||||
void CTFInit();
|
||||
void CTFSpawn();
|
||||
void CTFPrecache();
|
||||
bool G_TeamplayEnabled();
|
||||
void G_AdjustTeamScore(ctfteam_t team, int32_t offset);
|
||||
|
||||
void SP_info_player_team1(edict_t *self);
|
||||
void SP_info_player_team2(edict_t *self);
|
||||
|
||||
const char *CTFTeamName(int team);
|
||||
const char *CTFOtherTeamName(int team);
|
||||
void CTFAssignSkin(edict_t *ent, const char *s);
|
||||
void CTFAssignTeam(gclient_t *who);
|
||||
edict_t *SelectCTFSpawnPoint(edict_t *ent, bool force_spawn);
|
||||
bool CTFPickup_Flag(edict_t *ent, edict_t *other);
|
||||
void CTFDrop_Flag(edict_t *ent, gitem_t *item);
|
||||
void CTFEffects(edict_t *player);
|
||||
void CTFCalcScores();
|
||||
void CTFCalcRankings(std::array<uint32_t, MAX_CLIENTS> &player_ranks); // [Paril-KEX]
|
||||
void CheckEndTDMLevel(); // [Paril-KEX]
|
||||
void SetCTFStats(edict_t *ent);
|
||||
void CTFDeadDropFlag(edict_t *self);
|
||||
void CTFScoreboardMessage(edict_t *ent, edict_t *killer);
|
||||
void CTFTeam_f(edict_t *ent);
|
||||
void CTFID_f(edict_t *ent);
|
||||
#ifndef KEX_Q2_GAME
|
||||
void CTFSay_Team(edict_t *who, const char *msg);
|
||||
#endif
|
||||
void CTFFlagSetup(edict_t *ent);
|
||||
void CTFResetFlag(int ctf_team);
|
||||
void CTFFragBonuses(edict_t *targ, edict_t *inflictor, edict_t *attacker);
|
||||
void CTFCheckHurtCarrier(edict_t *targ, edict_t *attacker);
|
||||
void CTFDirtyTeamMenu();
|
||||
|
||||
// GRAPPLE
|
||||
void CTFWeapon_Grapple(edict_t *ent);
|
||||
void CTFPlayerResetGrapple(edict_t *ent);
|
||||
void CTFGrapplePull(edict_t *self);
|
||||
void CTFResetGrapple(edict_t *self);
|
||||
|
||||
// TECH
|
||||
gitem_t *CTFWhat_Tech(edict_t *ent);
|
||||
bool CTFPickup_Tech(edict_t *ent, edict_t *other);
|
||||
void CTFDrop_Tech(edict_t *ent, gitem_t *item);
|
||||
void CTFDeadDropTech(edict_t *ent);
|
||||
void CTFSetupTechSpawn();
|
||||
int CTFApplyResistance(edict_t *ent, int dmg);
|
||||
int CTFApplyStrength(edict_t *ent, int dmg);
|
||||
bool CTFApplyStrengthSound(edict_t *ent);
|
||||
bool CTFApplyHaste(edict_t *ent);
|
||||
void CTFApplyHasteSound(edict_t *ent);
|
||||
void CTFApplyRegeneration(edict_t *ent);
|
||||
bool CTFHasRegeneration(edict_t *ent);
|
||||
void CTFRespawnTech(edict_t *ent);
|
||||
void CTFResetTech();
|
||||
|
||||
void CTFOpenJoinMenu(edict_t *ent);
|
||||
bool CTFStartClient(edict_t *ent);
|
||||
void CTFVoteYes(edict_t *ent);
|
||||
void CTFVoteNo(edict_t *ent);
|
||||
void CTFReady(edict_t *ent);
|
||||
void CTFNotReady(edict_t *ent);
|
||||
bool CTFNextMap();
|
||||
bool CTFMatchSetup();
|
||||
bool CTFMatchOn();
|
||||
void CTFGhost(edict_t *ent);
|
||||
void CTFAdmin(edict_t *ent);
|
||||
bool CTFInMatch();
|
||||
void CTFStats(edict_t *ent);
|
||||
void CTFWarp(edict_t *ent);
|
||||
void CTFBoot(edict_t *ent);
|
||||
void CTFPlayerList(edict_t *ent);
|
||||
|
||||
bool CTFCheckRules();
|
||||
|
||||
void SP_misc_ctf_banner(edict_t *ent);
|
||||
void SP_misc_ctf_small_banner(edict_t *ent);
|
||||
|
||||
void UpdateChaseCam(edict_t *ent);
|
||||
void ChaseNext(edict_t *ent);
|
||||
void ChasePrev(edict_t *ent);
|
||||
|
||||
void CTFObserver(edict_t *ent);
|
||||
|
||||
void SP_trigger_teleport(edict_t *ent);
|
||||
void SP_info_teleport_destination(edict_t *ent);
|
||||
|
||||
void CTFSetPowerUpEffect(edict_t *ent, effects_t def);
|
||||
282
rerelease/ctf/p_ctf_menu.cpp
Normal file
282
rerelease/ctf/p_ctf_menu.cpp
Normal file
@@ -0,0 +1,282 @@
|
||||
// Copyright (c) ZeniMax Media Inc.
|
||||
// Licensed under the GNU General Public License 2.0.
|
||||
#include "../g_local.h"
|
||||
|
||||
// Note that the pmenu entries are duplicated
|
||||
// this is so that a static set of pmenu entries can be used
|
||||
// for multiple clients and changed without interference
|
||||
// note that arg will be freed when the menu is closed, it must be allocated memory
|
||||
pmenuhnd_t *PMenu_Open(edict_t *ent, const pmenu_t *entries, int cur, int num, void *arg, UpdateFunc_t UpdateFunc)
|
||||
{
|
||||
pmenuhnd_t *hnd;
|
||||
const pmenu_t *p;
|
||||
int i;
|
||||
|
||||
if (!ent->client)
|
||||
return nullptr;
|
||||
|
||||
if (ent->client->menu)
|
||||
{
|
||||
gi.Com_Print("warning, ent already has a menu\n");
|
||||
PMenu_Close(ent);
|
||||
}
|
||||
|
||||
hnd = (pmenuhnd_t *) gi.TagMalloc(sizeof(*hnd), TAG_LEVEL);
|
||||
hnd->UpdateFunc = UpdateFunc;
|
||||
|
||||
hnd->arg = arg;
|
||||
hnd->entries = (pmenu_t *) gi.TagMalloc(sizeof(pmenu_t) * num, TAG_LEVEL);
|
||||
memcpy(hnd->entries, entries, sizeof(pmenu_t) * num);
|
||||
// duplicate the strings since they may be from static memory
|
||||
for (i = 0; i < num; i++)
|
||||
Q_strlcpy(hnd->entries[i].text, entries[i].text, sizeof(entries[i].text));
|
||||
|
||||
hnd->num = num;
|
||||
|
||||
if (cur < 0 || !entries[cur].SelectFunc)
|
||||
{
|
||||
for (i = 0, p = entries; i < num; i++, p++)
|
||||
if (p->SelectFunc)
|
||||
break;
|
||||
}
|
||||
else
|
||||
i = cur;
|
||||
|
||||
if (i >= num)
|
||||
hnd->cur = -1;
|
||||
else
|
||||
hnd->cur = i;
|
||||
|
||||
ent->client->showscores = true;
|
||||
ent->client->inmenu = true;
|
||||
ent->client->menu = hnd;
|
||||
|
||||
if (UpdateFunc)
|
||||
UpdateFunc(ent);
|
||||
|
||||
PMenu_Do_Update(ent);
|
||||
gi.unicast(ent, true);
|
||||
|
||||
return hnd;
|
||||
}
|
||||
|
||||
void PMenu_Close(edict_t *ent)
|
||||
{
|
||||
pmenuhnd_t *hnd;
|
||||
|
||||
if (!ent->client->menu)
|
||||
return;
|
||||
|
||||
hnd = ent->client->menu;
|
||||
gi.TagFree(hnd->entries);
|
||||
if (hnd->arg)
|
||||
gi.TagFree(hnd->arg);
|
||||
gi.TagFree(hnd);
|
||||
ent->client->menu = nullptr;
|
||||
ent->client->showscores = false;
|
||||
}
|
||||
|
||||
// only use on pmenu's that have been called with PMenu_Open
|
||||
void PMenu_UpdateEntry(pmenu_t *entry, const char *text, int align, SelectFunc_t SelectFunc)
|
||||
{
|
||||
Q_strlcpy(entry->text, text, sizeof(entry->text));
|
||||
entry->align = align;
|
||||
entry->SelectFunc = SelectFunc;
|
||||
}
|
||||
|
||||
#include "../g_statusbar.h"
|
||||
|
||||
void PMenu_Do_Update(edict_t *ent)
|
||||
{
|
||||
int i;
|
||||
pmenu_t *p;
|
||||
int x;
|
||||
pmenuhnd_t *hnd;
|
||||
const char *t;
|
||||
bool alt = false;
|
||||
|
||||
if (!ent->client->menu)
|
||||
{
|
||||
gi.Com_Print("warning: ent has no menu\n");
|
||||
return;
|
||||
}
|
||||
|
||||
hnd = ent->client->menu;
|
||||
|
||||
if (hnd->UpdateFunc)
|
||||
hnd->UpdateFunc(ent);
|
||||
|
||||
statusbar_t sb;
|
||||
|
||||
sb.xv(32).yv(8).picn("inventory");
|
||||
|
||||
for (i = 0, p = hnd->entries; i < hnd->num; i++, p++)
|
||||
{
|
||||
if (!*(p->text))
|
||||
continue; // blank line
|
||||
|
||||
t = p->text;
|
||||
|
||||
if (*t == '*')
|
||||
{
|
||||
alt = true;
|
||||
t++;
|
||||
}
|
||||
|
||||
sb.yv(32 + i * 8);
|
||||
|
||||
const char *loc_func = "loc_string";
|
||||
|
||||
if (p->align == PMENU_ALIGN_CENTER)
|
||||
{
|
||||
x = 0;
|
||||
loc_func = "loc_cstring";
|
||||
}
|
||||
else if (p->align == PMENU_ALIGN_RIGHT)
|
||||
{
|
||||
x = 260;
|
||||
loc_func = "loc_rstring";
|
||||
}
|
||||
else
|
||||
x = 64;
|
||||
|
||||
sb.xv(x);
|
||||
|
||||
sb.sb << loc_func;
|
||||
|
||||
if (hnd->cur == i || alt)
|
||||
sb.sb << '2';
|
||||
|
||||
sb.sb << " 1 \"" << t << "\" \"" << p->text_arg1 << "\" ";
|
||||
|
||||
if (hnd->cur == i)
|
||||
{
|
||||
sb.xv(56);
|
||||
sb.string2("\">\"");
|
||||
}
|
||||
|
||||
alt = false;
|
||||
}
|
||||
|
||||
gi.WriteByte(svc_layout);
|
||||
gi.WriteString(sb.sb.str().c_str());
|
||||
}
|
||||
|
||||
void PMenu_Update(edict_t *ent)
|
||||
{
|
||||
if (!ent->client->menu)
|
||||
{
|
||||
gi.Com_Print("warning: ent has no menu\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (level.time - ent->client->menutime >= 1_sec)
|
||||
{
|
||||
// been a second or more since last update, update now
|
||||
PMenu_Do_Update(ent);
|
||||
gi.unicast(ent, true);
|
||||
ent->client->menutime = level.time + 1_sec;
|
||||
ent->client->menudirty = false;
|
||||
}
|
||||
ent->client->menutime = level.time;
|
||||
ent->client->menudirty = true;
|
||||
}
|
||||
|
||||
void PMenu_Next(edict_t *ent)
|
||||
{
|
||||
pmenuhnd_t *hnd;
|
||||
int i;
|
||||
pmenu_t *p;
|
||||
|
||||
if (!ent->client->menu)
|
||||
{
|
||||
gi.Com_Print("warning: ent has no menu\n");
|
||||
return;
|
||||
}
|
||||
|
||||
hnd = ent->client->menu;
|
||||
|
||||
if (hnd->cur < 0)
|
||||
return; // no selectable entries
|
||||
|
||||
i = hnd->cur;
|
||||
p = hnd->entries + hnd->cur;
|
||||
do
|
||||
{
|
||||
i++;
|
||||
p++;
|
||||
if (i == hnd->num)
|
||||
{
|
||||
i = 0;
|
||||
p = hnd->entries;
|
||||
}
|
||||
if (p->SelectFunc)
|
||||
break;
|
||||
} while (i != hnd->cur);
|
||||
|
||||
hnd->cur = i;
|
||||
|
||||
PMenu_Update(ent);
|
||||
}
|
||||
|
||||
void PMenu_Prev(edict_t *ent)
|
||||
{
|
||||
pmenuhnd_t *hnd;
|
||||
int i;
|
||||
pmenu_t *p;
|
||||
|
||||
if (!ent->client->menu)
|
||||
{
|
||||
gi.Com_Print("warning: ent has no menu\n");
|
||||
return;
|
||||
}
|
||||
|
||||
hnd = ent->client->menu;
|
||||
|
||||
if (hnd->cur < 0)
|
||||
return; // no selectable entries
|
||||
|
||||
i = hnd->cur;
|
||||
p = hnd->entries + hnd->cur;
|
||||
do
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
i = hnd->num - 1;
|
||||
p = hnd->entries + i;
|
||||
}
|
||||
else
|
||||
{
|
||||
i--;
|
||||
p--;
|
||||
}
|
||||
if (p->SelectFunc)
|
||||
break;
|
||||
} while (i != hnd->cur);
|
||||
|
||||
hnd->cur = i;
|
||||
|
||||
PMenu_Update(ent);
|
||||
}
|
||||
|
||||
void PMenu_Select(edict_t *ent)
|
||||
{
|
||||
pmenuhnd_t *hnd;
|
||||
pmenu_t *p;
|
||||
|
||||
if (!ent->client->menu)
|
||||
{
|
||||
gi.Com_Print("warning: ent has no menu\n");
|
||||
return;
|
||||
}
|
||||
|
||||
hnd = ent->client->menu;
|
||||
|
||||
if (hnd->cur < 0)
|
||||
return; // no selectable entries
|
||||
|
||||
p = hnd->entries + hnd->cur;
|
||||
|
||||
if (p->SelectFunc)
|
||||
p->SelectFunc(ent, hnd);
|
||||
}
|
||||
41
rerelease/ctf/p_ctf_menu.h
Normal file
41
rerelease/ctf/p_ctf_menu.h
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) ZeniMax Media Inc.
|
||||
// Licensed under the GNU General Public License 2.0.
|
||||
|
||||
enum
|
||||
{
|
||||
PMENU_ALIGN_LEFT,
|
||||
PMENU_ALIGN_CENTER,
|
||||
PMENU_ALIGN_RIGHT
|
||||
};
|
||||
|
||||
struct pmenu_t;
|
||||
|
||||
using UpdateFunc_t = void (*)(edict_t *ent);
|
||||
|
||||
struct pmenuhnd_t
|
||||
{
|
||||
pmenu_t *entries;
|
||||
int cur;
|
||||
int num;
|
||||
void *arg;
|
||||
UpdateFunc_t UpdateFunc;
|
||||
};
|
||||
|
||||
using SelectFunc_t = void (*)(edict_t *ent, pmenuhnd_t *hnd);
|
||||
|
||||
struct pmenu_t
|
||||
{
|
||||
char text[64];
|
||||
int align;
|
||||
SelectFunc_t SelectFunc;
|
||||
char text_arg1[64];
|
||||
};
|
||||
|
||||
pmenuhnd_t *PMenu_Open(edict_t *ent, const pmenu_t *entries, int cur, int num, void *arg, UpdateFunc_t UpdateFunc);
|
||||
void PMenu_Close(edict_t *ent);
|
||||
void PMenu_UpdateEntry(pmenu_t *entry, const char *text, int align, SelectFunc_t SelectFunc);
|
||||
void PMenu_Do_Update(edict_t *ent);
|
||||
void PMenu_Update(edict_t *ent);
|
||||
void PMenu_Next(edict_t *ent);
|
||||
void PMenu_Prev(edict_t *ent);
|
||||
void PMenu_Select(edict_t *ent);
|
||||
Reference in New Issue
Block a user