60 if (!
game.sv_maxplayersperteam)
66 const Player* endOfPlayers = &
game.players[
game.sv_maxplayersperteam];
68 assert(lastPlayer >=
game.players);
69 assert(lastPlayer < endOfPlayers);
71 Player* player = lastPlayer;
74 if (player >= endOfPlayers)
86 if (!
game.sv_maxplayersperteam)
90 return &
game.players[
game.sv_maxplayersperteam];
92 const Player* endOfPlayers = &
game.players[
game.sv_maxplayersperteam * 2];
94 assert(lastPlayer >= &
game.players[
game.sv_maxplayersperteam]);
95 assert(lastPlayer < endOfPlayers);
97 Player* player = lastPlayer;
100 if (player >= endOfPlayers)
112 Player* player = lastPlayer;
115 if (player->isInUse())
128 Player* player = lastPlayer;
131 if (player->isInUse())
151 if (p->isInUse() && team == p->getTeam())
215 gi.PlayerPrintf(&player, printLevel, fmt, ap);
226 Actor* actor =
nullptr;
256 switch (check.
type) {
284 gi.Error(
"Missing edict type %i in G_AppearPerishEvent", check.
type);
304 const int team = player.getTeam();
307 if (!
level.num_alive[team])
310 Actor* actor =
nullptr;
329 return level.activeTeam;
339 if (!ent || !ent->
inuse) {
359 if (ent->
getTeam() != player.getTeam()) {
383 if (
level.activeTeam != player.getTeam()) {
405 if (TU > actor->
getTus()) {
423 if (actor->
dir == dir)
521 gi.DPrintf(
"G_ClientStateChange: unknown request %i, ignoring\n", reqState);
553 Item* item =
nullptr;
575 const invDef_t* bestContainer =
nullptr;
576 Item* theWeapon =
nullptr;
580 if (cont->
def()->
out >= tu)
582 Item* item =
nullptr;
589 bestContainer = cont->
def();
590 tu = bestContainer->
out;
599 return G_ActorInvMove(actor, bestContainer, theWeapon, invDef, 0, 0,
true);
646 int num =
gi.ReadShort();
679 gi.ReadFormat(
format, &pos, &
i, &firemode, &from);
680 G_ClientShoot(player, actor, pos,
i, firemode,
nullptr,
true, from);
684 int fx, fy, to, tx, ty;
685 gi.ReadFormat(
format, &from, &fx, &fy, &to, &tx, &ty);
688 gi.DPrintf(
"G_ClientAction: PA_INVMOVE Container index out of range. (from: %i, to: %i)\n", from, to);
718 gi.ReadFormat(
format, &hand, &fmIdx, &objIdx);
723 int resCrouch, resShot;
724 gi.ReadFormat(
format, &resShot, &resCrouch);
730 gi.Error(
"G_ClientAction: Unknown action!\n");
743 if (player.getTeam() > 0) {
749 int playersInGame = 0;
763 if (
level.num_spawnpoints[
i])
764 spawnCheck[spawnSpots++] =
i;
768 gi.Error(
"G_GetTeam: Not enough spawn spots in map!");
772 int randomSpot = rand() % spawnSpots;
774 const int team = spawnCheck[randomSpot];
776 gi.Error(
"G_GetTeam: Could not assign a team!");
778 gi.DPrintf(
"%s has been randomly assigned to team %i\n",
783 randomSpot = (randomSpot + 1) % spawnSpots;
794 gi.DPrintf(
"Get a team for teamplay for %s\n", player.pers.netname);
798 gi.BroadcastPrintf(
PRINT_CONSOLE,
"serverconsole: %s has chosen team %i\n", player.pers.netname,
i);
800 gi.DPrintf(
"Team %i is not valid - choose a team between 1 and %i\n",
i,
sv_maxteams->integer);
806 gi.DPrintf(
"Getting a multiplayer team for %s\n", player.pers.netname);
808 if (
level.num_spawnpoints[
i]) {
809 bool teamAvailable =
true;
814 if (p->getTeam() ==
i) {
817 teamAvailable =
false;
831 if (p->getTeam() ==
i) {
840 gi.DPrintf(
"No free team - disconnecting '%s'\n", player.pers.netname);
863 if (p->getTeam() == team)
869 player.setTeam(team);
875 if (!
level.num_spawnpoints[team])
876 gi.Error(
"No spawnpoints for team %i", team);
891 return player.getTeam();
908 return player->isReady();
923 level.activeTeam = player.getTeam();
936 for (j = 0; j < teamCount; j++) {
937 if (p->getTeam() == knownTeams[j])
941 knownTeams[teamCount++] = p->getTeam();
945 const int teamIndex = (
int) (
frand() * (teamCount - 1) + 0.5);
947 level.activeTeam = knownTeams[teamIndex];
951 if (p->getTeam() !=
level.activeTeam)
968 Edict* ent =
nullptr;
969 if (
level.noRandomSpawn) {
971 if (ent->
type == spawnType && player.getTeam() == ent->
getTeam()) {
980 if (ent->
type == spawnType && player.getTeam() == ent->
getTeam()) {
987 return list[rand() %
count];
1019 actor->
think =
nullptr;
1030 actor->
think =
nullptr;
1049 if (copy !=
nullptr)
1058 if (copy !=
nullptr) {
1065 gi.Error(
"G_ClientGetFreeSpawnPointForActorSize: unknown fieldSize for actor edict (actorSize: %i)\n", actorSize);
1105 for (
int nr =
gi.ReadShort(); nr > 0; nr--) {
1110 if (container->
temp)
1111 gi.Error(
"G_ClientReadInventory failed, tried to add '%s' to a temp container %i", item.
def()->
id, container->
id);
1114 Com_Printf(
"G_ClientReadInventory: Item %s exceeds ent %i weight capacity\n", item.
def()->
id, ent->
getIdNum());
1115 if (!
level.noEquipment &&
game.invi.addToInventory(&ent->
chr.
inv, &item, container, x, y, 1) ==
nullptr)
1116 gi.Error(
"G_ClientReadInventory failed, could not add item '%s' to container %i (x:%i,y:%i)",
1117 item.
def()->
id, container->
id, x, y);
1140 const int teamDefIdx =
gi.ReadByte();
1142 gi.Error(
"Invalid team definition index given: %i", teamDefIdx);
1179 const int n =
gi.ReadShort();
1180 for (
int i = 0;
i < n;
i++) {
1220 const int ucn =
gi.ReadShort();
1223 gi.DPrintf(
"Could not find character on team %i with unique character number %i\n", player.getTeam(), ucn);
1233 const int saveTU = actor->
getTus();
1237 const int objIdx =
gi.ReadShort();
1239 if (objIdx !=
NONE) {
1277 gi.DPrintf(
"Not enough spawn points for team %i (actorsize: %i)\n", player.getTeam(), actorFieldSize);
1284 Com_Printf(
"Used inventory slots client %s spawn: %i\n", player.pers.netname,
game.invi.GetUsedSlots());
1325 player.began =
true;
1345 gi.ConfigString(
CS_PLAYERNAMES + player.getNum(),
"%s", player.pers.netname);
1348 gi.BroadcastPrintf(
PRINT_CONSOLE,
"%s has joined team %i\n", player.pers.netname, player.getTeam());
1386 gi.BroadcastPrintf(
PRINT_CONSOLE,
"%s has taken control over team %i.\n", player.pers.netname, player.getTeam());
1395 const bool alreadyReady = player.isReady();
1400 userinfo =
"\\cl_name\\badinfo";
1404 Q_strncpyz(player.pers.userinfo, userinfo,
sizeof(player.pers.userinfo));
1409 gi.ConfigString(
CS_PLAYERNAMES + player.getNum(),
"%s", player.pers.netname);
1414 if (!alreadyReady || !player.isReady()) {
1419 player.pers.netname);
1440 Com_Printf(
"connection attempt from %s\n", value);
1460 if (player->isInUse()) {
1461 gi.BroadcastPrintf(
PRINT_CONSOLE,
"%s already in use.\n", player->pers.netname);
1469 gi.BroadcastPrintf(
PRINT_CONSOLE,
"%s is connecting...\n", player->pers.netname);
1483 if (
level.activeTeam == player.getTeam())
1492 Actor* actor =
nullptr;
1494 if (actor->
pnum == player.num)
1500 player.began =
false;
1501 player.roundDone =
false;
1502 player.setReady(
false);
1504 gi.BroadcastPrintf(
PRINT_CONSOLE,
"%s disconnected.\n", player.pers.netname);
const char * CHRSH_CharGetBody(const character_t *const chr)
Returns the body model for the soldiers for armoured and non armoured soldiers.
const char * CHRSH_CharGetHead(const character_t *const chr)
Returns the head model for the soldiers for armoured and non armoured soldiers.
#define INVDEF(containerID)
void setBody(unsigned int body_)
void setHead(unsigned int head_)
short numBodyParts(void) const
Item * getNextItem(const Item *prev) const
const invDef_t * def() const
void setPlayerNum(int num)
Item * getRightHandItem() const
actorSizeEnum_t fieldSize
void(* think)(Edict *self)
Player & getPlayer() const
Item * getContainer(const containerIndex_t idx) const
bool canHoldItemWeight(containerIndex_t from, containerIndex_t to, const Item &item, int maxWeight) const
Check that adding an item to the inventory won't exceed the max permitted weight.
int getWeight() const
Get the weight of the items in the given inventory (excluding those in temp containers).
Item * getItemAtPos(const invDef_t *container, const int x, const int y) const
Searches if there is an item at location (x,y) in a container.
const Container * getNextCont(const Container *prev, bool inclTemp=false) const
item instance data, with linked list capability
const objDef_t * def(void) const
bool isHeldTwoHanded() const
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
void Com_Printf(const char *const fmt,...)
#define ACTOR_SIZE_NORMAL
void G_ActorReserveTUs(Edict *ent, int resReaction, int resShot, int resCrouch)
Reserves TUs for different actor actions.
bool G_ActorDieOrStun(Actor *actor, Edict *attacker)
Reports and handles death or stun of an actor. If the HP of an actor is zero the actor will die,...
void G_ActorGiveTimeUnits(Actor *actor)
Set time units for the given edict. Based on speed skills.
int G_ActorUsableTUs(const Edict *ent)
Calculates the amount of usable TUs. This is without the reserved TUs.
void G_ActorModifyCounters(const Edict *attacker, const Edict *victim, int deltaAlive, int deltaKills, int deltaStuns)
void G_ActorUseDoor(Actor *actor, Edict *door)
Make the actor use (as in open/close) a door edict.
void G_ActorSetTU(Edict *ent, int tus)
static bool G_ActorDie(Actor *actor, const Edict *attacker)
void G_ActorUseTU(Edict *ent, int tus)
int G_ActorDoTurn(Edict *ent, byte dir)
Turns an actor around.
void G_ActorSetMaxs(Actor *actor)
Sets correct bounding box for actor (state dependent).
bool G_ActorInvMove(Actor *actor, const invDef_t *fromContType, Item *fItem, const invDef_t *toContType, int tx, int ty, bool checkaction)
Moves an item inside an inventory. Floors are handled special.
int G_ActorGetContentFlags(const vec3_t origin)
Get the content flags from where the actor is currently standing.
#define G_SetState(ent, s)
#define G_ToggleCrouched(ent)
Artificial Intelligence functions.
int AIL_InitActor(Actor *actor)
Initializes the lua AI for an actor.
playermask_t G_TeamToPM(int team)
Generates the player bit mask for a given team.
bool G_SetTeamForPlayer(Player &player, const int team)
Set the used team for the given player.
void G_ResetClientData(void)
Called after every player has joined.
static void G_ClientReadCharacter(Edict *ent)
Reads the character data from the netchannel that is needed to spawn an actor.
static void G_ClientStateChangeUpdate(Edict &ent)
After an actor changed his state, he might get visible for other players. Check the vis here and send...
Player * G_PlayerGetNextActiveHuman(Player *lastPlayer)
Iterate through the list of players.
bool G_ActionCheckForCurrentTeam(const Player &player, Actor *ent, int TU)
Checks whether the requested action is possible for the current active team.
Player * G_PlayerGetNextHuman(Player *lastPlayer)
Iterate through the list of players.
Player * G_PlayerGetNextActiveAI(Player *lastPlayer)
Iterate through the list of players.
void G_GiveTimeUnits(int team)
Network function to update the time units (TUs) for each team-member.
static void G_ClientSendEdictsAndBrushModels(const Player &player)
Send brush models for entities like func_breakable and func_door and triggers with their bounding box...
static void G_ThinkActorGoCrouch(Edict *ent)
Think function for actors that spawn crouched.
static bool G_ActorSpawnIsAllowed(const int num, const int team)
Checks whether the spawn of an actor is allowed for the current running match.
void G_ClientUserinfoChanged(Player &player, const char *userinfo)
called whenever the player updates a userinfo variable.
bool G_ClientUseEdict(const Player &player, Actor *actor, Edict *edict)
This function 'uses' the edict. E.g. it opens the door when the player wants it to open.
int G_ClientGetTeamNumPref(const Player &player)
Returns the preferred team number for the player.
int G_GetActiveTeam(void)
Returns the current active team to the server.
static void G_ThinkActorDieAfterSpawn(Edict *ent)
Think function for actors that spawn dead.
static void G_ClientSkipActorInfo(void)
Call this if you want to skip some actor netchannel data.
static bool G_ActionCheck(const Player &player, Edict *ent)
Checks whether the requested action is possible.
bool G_ClientIsReady(const Player *player)
static Edict * G_ClientGetFreeSpawnPoint(const Player &player, int spawnType)
Find valid actor spawn fields for this player.
void G_ClientDisconnect(Player &player)
void G_ClientStateChange(const Player &player, Actor *actor, int reqState, bool checkaction)
Changes the state of a player/soldier.
static chrScoreMission_t scoreMission[MAX_EDICTS]
void G_AppearPerishEvent(playermask_t playerMask, bool appear, Edict &check, const Edict *ent)
Send the appear or perish event to the affected clients.
static void G_GetStartingTeam(const Player &player)
Chose a team that should start the match.
static void G_ClientAssignDefaultActorValues(Actor *actor)
Used after spawning an actor to set some default values that are not read from the network event.
void G_SendInvisible(const Player &player)
This function sends all the actors to the client that are not visible initially - this is needed beca...
void G_ClientPrintf(const Player &player, int printLevel, const char *fmt,...)
bool G_ClientBegin(Player &player)
This functions starts the client.
int G_ClientGetTeamNum(const Player &player)
Returns the assigned team number of the player.
int G_ClientAction(Player &player)
The client sent us a message that he did something. We now execute the related function(s) and notify...
bool G_ClientConnect(Player *player, char *userinfo, size_t userinfoSize)
Checks whether the connection is valid or invalid and set some user info keys.
Player * G_PlayerGetNextAI(Player *lastPlayer)
Iterate through the list of players.
Actor * G_ClientGetFreeSpawnPointForActorSize(const Player &player, const actorSizeEnum_t actorSize)
Searches a free spawning point for a given actor size and turns it into an actor.
bool G_ActionCheckForReaction(const Player &player, Actor *actor, int TU)
Checks whether the requested action is possible.
bool G_ClientCanReload(Actor *actor, containerIndex_t containerID)
Returns true if actor can reload weapon.
void G_ClientStartMatch(Player &player)
Sets the team, init the TU and sends the player stats.
bool G_ClientGetWeaponFromInventory(Actor *actor)
Retrieve or collect a loaded weapon from any linked container for the actor's right hand.
static void G_ClientTurn(Player &player, Actor *actor, dvec_t dvec)
Sends the actual actor turn event over the netchannel.
static void G_ClientReadInventory(Edict *ent)
Read the inventory from the clients team data.
teammask_t G_PMToVis(playermask_t playerMask)
Converts player mask to vis mask.
static int scoreMissionNum
void G_ClientInitActorStates(const Player &player)
This is called after the actors are spawned and will set actor states without consuming TUs.
playermask_t G_VisToPM(teammask_t teamMask)
Converts vis mask to player mask.
void G_ClientTeamInfo(const Player &player)
The client lets the server spawn the actors for a given player by sending their information (models,...
static void G_GetTeam(Player &player)
Sets the teamnum var for this match.
Interface for g_client.cpp.
bool G_ClientShoot(const Player &player, Actor *actor, const pos3_t at, shoot_types_t shootType, fireDefIndex_t firemode, shot_mock_t *mock, bool allowReaction, int z_align)
Setup for shooting, either real or mock.
All parts of the main game logic that are combat related.
Actor * makeActor(Edict *ent)
Convert an Edict pointer into an Actor pointer.
Edict * G_EdictsGetFirst(void)
Returns the first entity.
Actor * G_EdictsGetNextLivingActorOfTeam(Actor *lastEnt, const int team)
Iterate through the living actor entities of the given team.
Actor * G_EdictsGetActorByUCN(const int ucn, const int team)
Searches an actor by a unique character number.
Actor * G_EdictsGetNextActor(Actor *lastEnt)
Iterate through the actor entities (even the dead!).
Actor * G_EdictsGetNextLivingActor(Actor *lastEnt)
Iterate through the living actor entities.
Edict * G_EdictDuplicate(const Edict *edict)
Edict * G_EdictsGetNextInUse(Edict *lastEnt)
Iterate through the entities that are in use.
Actor * G_EdictsGetLivingActorFromPos(const pos3_t pos)
Searches an actor at the given grid location.
Edict * G_EdictsGetByNum(const int num)
Get an entity by it's number.
functions to handle the storage and lifecycle of all edicts in the game module.
void G_EventSendParticle(playermask_t playerMask, const Edict &ent)
void G_EventReactionFireChange(const Edict &ent)
void G_EventActorTurn(const Edict &ent)
Send the turn event for the given entity.
void G_EventActorAppear(playermask_t playerMask, const Actor &check, const Edict *ent)
void G_EventAddBrushModel(playermask_t playerMask, const Edict &ent)
void G_EventStart(const Player &player, bool teamplay)
void G_EventCameraAppear(playermask_t playerMask, const Edict &ent)
Send an appear event to the client.
void G_EventEdictPerish(playermask_t playerMask, const Edict &ent)
Send disappear event.
void G_EventReset(const Player &player, int activeTeam)
void G_EventSendState(playermask_t playerMask, const Edict &ent)
void G_EventActorAdd(playermask_t playerMask, const Edict &ent, const bool instant)
void G_EventEdictAppear(playermask_t playerMask, const Edict &ent)
Send an appear event to the client.
#define G_PlayerToPM(player)
unsigned int playermask_t
void G_SendInventory(playermask_t playerMask, const Edict &ent)
Sends whole inventory through the network buffer.
void G_ReadItem(Item *item, const invDef_t **container, int *x, int *y)
Read item from the network buffer.
#define G_IsVisibleOnBattlefield(ent)
#define G_IsVisibleForTeam(ent, team)
#define G_TeamToVisMask(team)
bool SV_FilterPacket(const char *from)
void G_SendStats(Edict &ent)
Send stats to network buffer.
#define G_IsAIPlayer(player)
#define G_IsMultiPlayer()
void G_ClientEndRound(Player &player)
#define G_IsSinglePlayer()
cvar_t * sv_maxsoldiersperplayer
cvar_t * sv_roundtimelimit
cvar_t * sv_maxsoldiersperteam
void G_SendPlayerStats(const Player &player)
Write player stats to network buffer.
#define FL_DESTROYABLE
If an edict is destroyable (like ET_BREAKABLE, ET_DOOR [if health set] or maybe a ET_MISSION [if heal...
bool G_MatchIsRunning(void)
Checks whether the game is running (active team and no intermission time).
void G_MatchEndCheck(void)
Checks whether there are still actors to fight with left. If none are the match end will be triggered...
void G_ClientMove(const Player &player, int visTeam, Actor *actor, const pos3_t to)
Generates the client events that are send over the netchannel to move an actor.
void G_ReactionFireSettingsUpdate(Actor *actor, fireDefIndex_t fmIdx, actorHands_t hand, const objDef_t *od)
Updates the reaction fire settings in case something was moved into a hand or from a hand that would ...
void G_ReactionFireTargetsCreate(const Edict *shooter)
free function to create a table of reaction fire targets for the given edict.
bool G_ReactionFireSettingsReserveTUs(Actor *ent)
Set the reaction fire TU reservation for an actor.
bool G_UseEdict(Edict *ent, Edict *activator)
Call the 'use' function for the given edict and all its group members.
void G_PrintStats(const char *format,...)
Prints stats to game console and stats log file.
int G_TouchTriggers(Edict *ent, const entity_type_t type)
Check the world against triggers for the current entity.
Misc utility functions for game module.
void G_VisFlagsAdd(Edict &ent, teammask_t teamMask)
void G_VisFlagsClear(int team)
Reset the visflags for all edicts in the global list for the given team - and only for the given team...
int G_CheckVisTeamAll(const int team, const vischeckflags_t visFlags, const Edict *ent)
Do G_CheckVisTeam for all entities ent is the one that is looking at the others.
void G_VisFlagsReset(Edict &ent)
void G_VisFlagsSwap(Edict &ent, teammask_t teamMask)
void G_CheckVis(Edict *check, const vischeckflags_t visFlags)
Check if the edict appears/perishes for the other teams. If they appear for other teams,...
void G_CheckVisPlayer(Player &player, const vischeckflags_t visFlags)
Sets visible edict on player spawn.
const char * Info_ValueForKey(const char *s, const char *key)
Searches the string for the given key and returns the associated value, or an empty string.
void Info_SetValueForKey(char *s, const size_t size, const char *key, const char *value)
Adds a new entry into string with given value.
void Info_SetValueForKeyAsInteger(char *s, const size_t size, const char *key, const int value)
bool Info_Validate(const char *s)
Some characters are illegal in info strings because they can mess up the server's parsing.
int Info_IntegerForKey(const char *s, const char *key)
const objDef_t * INVSH_GetItemByIDX(int index)
Returns the item that belongs to the given index or nullptr if the index is invalid.
bool isValidContId(const containerIndex_t id)
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
float frand(void)
Return random values between 0 and 1.
short dvec_t
The direction vector tells us where the actor came from (in his previous step). The pathing table hol...
const char * pa_format[]
Player action format strings for netchannel transfer.
void format(__printf__, 1, 2)))
#define REJ_PASSWORD_REQUIRED_OR_INCORRECT
Reject messages that are send to the client from the game module.
QGL_EXTERN GLuint GLsizei GLsizei * length
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
chrReservations_t reservedTus
const teamDef_t * teamDef
chrScoreMission_t * scoreMission
actorSizeEnum_t fieldSize
int stuns[KILLED_NUM_TYPES]
int kills[KILLED_NUM_TYPES]
int skills[SKILL_NUM_TYPES]
int experience[SKILL_NUM_TYPES+1]
Structure of all stats collected in a mission.
inventory definition for our menus
Defines all attributes of objects used in the inventory.
bool isLoadableInWeapon(const objDef_s *weapon) const
Checks if an item can be used to reload a weapon.
const BodyData * bodyTemplate
int treatmentLevel[BODYPART_MAXTYPE]