void G_EventReactionFireAddTarget (const Edict& shooter, const Edict& target, int tus, int step) { gi.QueueEvent(G_PlayerToPM(shooter.getPlayer()), EV_ACTOR_REACTIONFIREADDTARGET, shooter.getIdNum()); gi.QueueWriteShort(target.getIdNum()); gi.QueueWriteByte(tus); gi.QueueWriteByte(step); }
void G_EventReset (const Player& player, int activeTeam) { G_EventAdd(G_PlayerToPM(player), EV_RESET | EVENT_INSTANTLY, -1); gi.WriteByte(player.getTeam()); gi.WriteByte(activeTeam); G_EventEnd(); }
void G_EventReset (const player_t *player, int activeTeam) { G_EventAdd(G_PlayerToPM(player), EV_RESET | EVENT_INSTANTLY, -1); gi.WriteByte(player->pers.team); gi.WriteByte(activeTeam); G_EventEnd(); }
void G_EventReactionFireTargetUpdate (const Edict& shooter, const Edict& target, int tus, int step) { gi.QueueEvent(G_PlayerToPM(shooter.getPlayer()), EV_ACTOR_REACTIONFIRETARGETUPDATE, shooter.number); gi.QueueWriteShort(target.number); gi.QueueWriteByte(tus); gi.QueueWriteByte(step); }
/** * @brief Will inform the player about the real TU reservation * @param ent The actors edict. */ void G_EventActorSendReservations (const edict_t *ent) { G_EventAdd(G_PlayerToPM(G_PLAYER_FROM_ENT(ent)), EV_ACTOR_RESERVATIONCHANGE, ent->number); gi.WriteShort(ent->chr.reservedTus.reaction); gi.WriteShort(ent->chr.reservedTus.shot); gi.WriteShort(ent->chr.reservedTus.crouch); G_EventEnd(); }
/** * @brief Actor has been wounded/treated * @param[in] ent The actor whose wound status has changed * @note This event is sent to the player this actor belongs to */ void G_EventActorWound (const edict_t *ent, const int bodyPart) { const int mask = G_PlayerToPM(G_PLAYER_FROM_ENT(ent)); G_EventAdd(mask, EV_ACTOR_WOUND, ent->number); gi.WriteByte(bodyPart); gi.WriteByte(ent->chr.wounds.woundLevel[bodyPart]); gi.WriteByte(ent->chr.wounds.treatmentLevel[bodyPart]); G_EventEnd(); }
/** * @brief Send info about an actor's wounds to the client. * @param[in] ent The actor whose wound status we are sending. * @param[in] bodyPart The body part index we are sending wound info about. * @note This event is sent to the player this actor belongs to */ void G_EventActorWound (const Edict& ent, const int bodyPart) { const int mask = G_PlayerToPM(ent.getPlayer()); G_EventAdd(mask, EV_ACTOR_WOUND, ent.number); gi.WriteByte(bodyPart); const woundInfo_t& wounds = ent.chr.wounds; gi.WriteByte(wounds.woundLevel[bodyPart]); gi.WriteByte(wounds.treatmentLevel[bodyPart]); G_EventEnd(); }
/** * @brief Sets visible edict on player spawn * @sa G_ClientStartMatch * @sa G_CheckVisTeam * @sa G_AppearPerishEvent */ void G_CheckVisPlayer (Player& player, const vischeckflags_t visFlags) { Edict* ent = nullptr; /* check visibility */ while ((ent = G_EdictsGetNextInUse(ent))) { /* check if he's visible */ G_DoTestVis(player.getTeam(), ent, visFlags, G_PlayerToPM(player), nullptr); } }
/** * @brief Will inform the player about the real TU reservation * @param ent The actors edict. */ void G_EventActorSendReservations (const Edict& ent) { G_EventAdd(G_PlayerToPM(ent.getPlayer()), EV_ACTOR_RESERVATIONCHANGE, ent.number); const chrReservations_t& reservedTUs = ent.chr.reservedTus; gi.WriteShort(reservedTUs.reaction); gi.WriteShort(reservedTUs.shot); gi.WriteShort(reservedTUs.crouch); G_EventEnd(); }
/** * @brief Write player stats to network buffer * @sa G_SendStats */ void G_SendPlayerStats (const Player& player) { Edict* ent = nullptr; while ((ent = G_EdictsGetNextActor(ent))) if (ent->team == player.getTeam()) { G_EventActorStats(*ent, G_PlayerToPM(player)); G_SendWoundStats(ent); } }
void G_EventReactionFireChange (const edict_t* ent) { const objDef_t *od = ent->chr.RFmode.weapon; G_EventAdd(G_PlayerToPM(G_PLAYER_FROM_ENT(ent)), EV_ACTOR_REACTIONFIRECHANGE, ent->number); gi.WriteByte(ent->chr.RFmode.fmIdx); gi.WriteByte(ent->chr.RFmode.getHand()); gi.WriteShort(od ? od->idx : NONE); G_EventEnd(); }
void G_EventReactionFireChange (const Edict& ent) { const FiremodeSettings& fireMode = ent.chr.RFmode; const objDef_t* od = fireMode.getWeapon(); G_EventAdd(G_PlayerToPM(ent.getPlayer()), EV_ACTOR_REACTIONFIRECHANGE, ent.number); gi.WriteByte(fireMode.getFmIdx()); gi.WriteByte(fireMode.getHand()); gi.WriteShort(od ? od->idx : NONE); G_EventEnd(); }
/** * @brief Sets visible edict on player spawn * @sa G_ClientStartMatch * @sa G_CheckVisTeam * @sa G_AppearPerishEvent */ int G_CheckVisPlayer (player_t* player, bool perish) { int status = 0; edict_t* ent = NULL; /* check visibility */ while ((ent = G_EdictsGetNextInUse(ent))) { /* check if he's visible */ status |= G_DoTestVis(player->pers.team, ent, perish, G_PlayerToPM(player), NULL); } return status; }
/** * @brief Converts player mask to vis mask * @param[in] playerMask The player bit mask (contains the player numbers) that * is converted to a vis mask * @return Returns a vis mask for all the teams of the connected players that * are marked in the given @c playerMask. */ teammask_t G_PMToVis (playermask_t playerMask) { player_t *p; teammask_t teamMask = 0; /* don't handle the ai players, here */ p = NULL; while ((p = G_PlayerGetNextActiveHuman(p))) { if (playerMask & G_PlayerToPM(p)) teamMask |= G_TeamToVisMask(p->pers.team); } return teamMask; }
/** * @brief Converts vis mask to player mask * @param[in] vis_mask The visibility bit mask (contains the team numbers) that * is converted to a player mask * @return Returns a playermask for all the teams of the connected players that * are marked in the given @c vis_mask. */ unsigned int G_VisToPM (vismask_t vis_mask) { player_t *p; unsigned int playerMask; playerMask = 0; /* don't handle the ai players, here */ p = NULL; while ((p = G_PlayerGetNextActiveHuman(p))) { if (vis_mask & G_TeamToVisMask(p->pers.team)) playerMask |= G_PlayerToPM(p); } return playerMask; }
/** * @brief Generates the player bit mask for a given team * @param[in] team The team to create the player bit mask for * @note E.g. multiplayer team play can have more than one human player on the * same team. */ playermask_t G_TeamToPM (int team) { player_t *p; playermask_t playerMask; playerMask = 0; /* don't handle the ai players, here */ p = NULL; while ((p = G_PlayerGetNextHuman(p))) { if (p->inuse && team == p->pers.team) playerMask |= G_PlayerToPM(p); } return playerMask; }
/** * @brief This function sends all the actors to the client that are not visible * initially - this is needed because an actor can e.g. produce sounds that are * send over the net. And the client can only handle them if he knows the * @c le_t (local entity) already * @note Call this for the first @c G_CheckVis call for every new * actor or player * @sa G_CheckVis * @sa CL_ActorAdd */ void G_SendInvisible (const player_t* player) { const int team = player->pers.team; assert(team != TEAM_NO_ACTIVE); if (level.num_alive[team]) { edict_t* ent = NULL; /* check visibility */ while ((ent = G_EdictsGetNextActor(ent))) { if (ent->team != team) { /* not visible for this team - so add the le only */ if (!G_IsVisibleForTeam(ent, team)) { G_EventActorAdd(G_PlayerToPM(player), ent); } } } } }
/** * @brief Send brush models for entities like func_breakable and func_door and triggers * with their bounding boxes to the client and let him know about them. * There are also entities that are announced here, but fully handled clientside - like * func_rotating. * @sa CL_AddBrushModel * @sa EV_ADD_BRUSH_MODEL * @param[in] player The player the edicts are send to */ static void G_ClientSendEdictsAndBrushModels (const player_t *player) { const int mask = G_PlayerToPM(player); /* skip the world */ edict_t *ent = G_EdictsGetFirst(); /* make SOLID_BSP edicts visible to the client */ while ((ent = G_EdictsGetNextInUse(ent))) { /* brush models that have a type - not the world - keep in * mind that there are several world edicts in the list in case of * a map assembly */ if (ent->solid != SOLID_BSP) continue; /* skip the world(s) in case of map assembly */ if (ent->type > ET_NULL) { G_EventAddBrushModel(mask, ent); G_VisFlagsAdd(ent, ~ent->visflags); } } }
/** * @brief Checks whether the connection is valid or invalid and set some * user info keys. * @param[in,out] player The player that is trying to connect to the game * @param[in,out] userinfo The userinfo data that is checked and changed * @param[in] userinfoSize The size of the userinfo buffer * @sa G_ClientDisconnect * @sa CL_ConnectionlessPacket * @todo Check if the teamnum preference has already reached maxsoldiers * and reject connection if so * @return @c false if the connection is refused, @c true otherwise */ bool G_ClientConnect (player_t * player, char *userinfo, size_t userinfoSize) { const char *value; value = Info_ValueForKey(userinfo, "ip"); Com_Printf("connection attempt from %s\n", value); /* check to see if they are on the banned IP list */ if (SV_FilterPacket(value)) { Info_SetValueForKey(userinfo, userinfoSize, "rejmsg", REJ_BANNED); return false; } if (!G_PlayerToPM(player)) { Info_SetValueForKey(userinfo, userinfoSize, "rejmsg", "Server is full"); return false; } value = Info_ValueForKey(userinfo, "password"); if (password->string[0] != '\0' && !Q_streq(password->string, "none") && !Q_streq(password->string, value)) { Info_SetValueForKey(userinfo, userinfoSize, "rejmsg", REJ_PASSWORD_REQUIRED_OR_INCORRECT); return false; } /* fix for fast reconnects after a disconnect */ if (player->inuse) { gi.BroadcastPrintf(PRINT_CONSOLE, "%s already in use.\n", player->pers.netname); G_ClientDisconnect(player); } /* reset persistent data */ OBJZERO(player->pers); G_ClientUserinfoChanged(player, userinfo); gi.BroadcastPrintf(PRINT_CONSOLE, "%s is connecting...\n", player->pers.netname); return true; }
/** * @brief Hurt trigger * @sa SP_trigger_hurt */ bool Touch_HurtTrigger (Edict* self, Edict* activator) { /* Dead actors should really not be able to trigger this - they can't be hurt anymore anyway */ if (!G_IsLivingActor(activator)) return false; /* If no damage is dealt don't count it as triggered */ const int damage = G_ApplyProtection(activator, self->dmgtype, self->dmg); if (damage == 0) return false; const bool stunEl = (self->dmgtype == gi.csi->damStunElectro); const bool stunGas = (self->dmgtype == gi.csi->damStunGas); const bool shock = (self->dmgtype == gi.csi->damShock); const bool isRobot = activator->chr.teamDef->robot; Actor* actor = makeActor(activator); if (stunEl || (stunGas && !isRobot)) { actor->addStun(damage); } else if (shock) { /** @todo Handle dazed via trigger_hurt */ } else { G_TakeDamage(actor, damage); } /* Play hurt sound unless this is shock damage -- it doesn't do anything * because we don't actually handle it above yet */ if (!shock) { const teamDef_t* teamDef = activator->chr.teamDef; const int gender = activator->chr.gender; const char* sound = teamDef->getActorSound(gender, SND_HURT); G_EventSpawnSound(G_PlayerToPM(activator->getPlayer()), *activator, nullptr, sound); } G_CheckDeathOrKnockout(actor, nullptr, nullptr, damage); return true; }
/** * @brief Reset the client actions for the given entity * @param[in] ent The entity to reset the client action for * @note This event is send to the player this edict belongs to */ void G_EventResetClientAction (const edict_t* ent) { const int playerMask = G_PlayerToPM(G_PLAYER_FROM_ENT(ent)); G_EventAdd(playerMask, EV_RESET_CLIENT_ACTION, ent->number); G_EventEnd(); }
void G_EventReactionFireAbortShot (const Edict& shooter, const Edict& target, int step) { gi.QueueEvent(G_PlayerToPM(shooter.getPlayer()), EV_ACTOR_REACTIONFIREABORTSHOT, shooter.getIdNum()); gi.QueueWriteShort(target.getIdNum()); gi.QueueWriteByte(step); }
void G_EventStart (const Player& player, bool teamplay) { G_EventAdd(G_PlayerToPM(player), EV_START | EVENT_INSTANTLY, -1); gi.WriteByte(teamplay); G_EventEnd(); }
void G_EventReactionFireRemoveTarget (const Edict& shooter, const Edict& target, int step) { gi.QueueEvent(G_PlayerToPM(shooter.getPlayer()), EV_ACTOR_REACTIONFIREREMOVETARGET, shooter.number); gi.QueueWriteShort(target.number); gi.QueueWriteByte(step); }
/** * @brief Reset the client actions for the given entity * @param[in] ent The entity to reset the client action for * @note This event is send to the player this edict belongs to */ void G_EventResetClientAction (const Edict& ent) { const int playerMask = G_PlayerToPM(ent.getPlayer()); G_EventAdd(playerMask, EV_RESET_CLIENT_ACTION, ent.number); G_EventEnd(); }