/** * @brief Check if reload is possible. * @param[in] le Pointer to local entity for which we handle an action on hud menu. * @param[in] weapon An item in hands. * @param[in] container The container to get the ammo from * @return qfalse when action is not possible, otherwise qtrue * @sa HUD_ReloadLeft_f * @sa HUD_ReloadRight_f */ static qboolean HUD_CheckReload (const le_t* le, const invList_t *weapon, containerIndex_t container) { int tus; if (!le) return qfalse; /* No item in hand. */ if (!weapon || !weapon->item.t) { HUD_DisplayMessage(_("No item in hand.\n")); return qfalse; } /* Cannot reload because this item is not reloadable. */ if (!weapon->item.t->reload) { HUD_DisplayMessage(_("Can't perform action:\nthis item is not reloadable.\n")); return qfalse; } tus = HUD_CalcReloadTime(le, weapon->item.t, container); /* Cannot reload because of no ammo in inventory. */ if (tus == -1) { HUD_DisplayMessage(_("Can't perform action:\nammo not available.\n")); return qfalse; } /* Cannot reload because of not enough TUs. */ if (le->TU < tus) { HUD_DisplayMessage(_("Can't perform action:\nnot enough TUs.\n")); return qfalse; } return qtrue; }
/** * @brief Check if shooting is possible. * i.e. The weapon has ammo and can be fired with the 'available' hands. * TUs (i.e. "time") are are _not_ checked here, this needs to be done * elsewhere for the correct firemode. * @sa HUD_FireWeapon_f * @return qfalse when action is not possible, otherwise qtrue */ static qboolean HUD_CheckShooting (const le_t* le, invList_t *weapon) { if (!le) return qfalse; /* No item in hand. */ if (!weapon || !weapon->item.t) { HUD_DisplayMessage(_("No item in hand.\n")); return qfalse; } /* Cannot shoot because of lack of ammo. */ if (weapon->item.a <= 0 && weapon->item.t->reload) { HUD_DisplayMessage(_("Can't perform action:\nout of ammo.\n")); return qfalse; } /* Cannot shoot because weapon is fireTwoHanded, yet both hands handle items. */ if (weapon->item.t->fireTwoHanded && LEFT(le)) { HUD_DisplayMessage(_("This weapon cannot be fired\none handed.\n")); return qfalse; } return qtrue; }
/** * @brief Finishes the current turn of the player in battlescape and starts the turn for the next team. */ static void CL_NextRound_f (void) { /* can't end round if we are not in battlescape */ if (!CL_BattlescapeRunning()) return; /* can't end round if we're not active */ if (!cls.isOurRound()) { HUD_DisplayMessage(_("It is not your turn!")); return; } /* send endround */ dbuffer msg; NET_WriteByte(&msg, clc_endround); NET_WriteMsg(cls.netStream, msg); }
/** * @brief Finishes the current round of the player in battlescape and starts the round for the next team. */ static void CL_NextRound_f (void) { struct dbuffer *msg; /* can't end round if we are not in battlescape */ if (!CL_BattlescapeRunning()) return; /* can't end round if we're not active */ if (cls.team != cl.actTeam) { HUD_DisplayMessage(_("This isn't your round")); return; } /* send endround */ msg = new_dbuffer(); NET_WriteByte(msg, clc_endround); NET_WriteMsg(cls.netStream, msg); }
/** * @brief Starts aiming/target mode for selected left/right firemode. * @note Previously know as a combination of CL_FireRightPrimary, CL_FireRightSecondary, * @note CL_FireLeftPrimary and CL_FireLeftSecondary. */ static void HUD_FireWeapon_f (void) { actorHands_t hand; fireDefIndex_t firemode; const objDef_t *ammo; const fireDef_t *fd; if (Cmd_Argc() < 3) { /* no argument given */ Com_Printf("Usage: %s <l|r> <firemode number>\n", Cmd_Argv(0)); return; } if (!selActor) return; hand = ACTOR_GET_HAND_INDEX(Cmd_Argv(1)[0]); firemode = atoi(Cmd_Argv(2)); if (firemode >= MAX_FIREDEFS_PER_WEAPON || firemode < 0) return; fd = HUD_GetFireDefinitionForHand(selActor, hand); if (fd == NULL) return; ammo = fd->obj; /* Let's check if shooting is possible. */ if (!HUD_CheckShooting(selActor, ACTOR_GET_INV(selActor, hand))) return; if (ammo->fd[fd->weapFdsIdx][firemode].time <= CL_ActorUsableTUs(selActor)) { /* Actually start aiming. This is done by changing the current mode of display. */ if (hand == ACTOR_HAND_RIGHT) CL_ActorSetMode(selActor, M_FIRE_R); else CL_ActorSetMode(selActor, M_FIRE_L); /* Store firemode. */ selActor->currentSelectedFiremode = firemode; } else { /* Cannot shoot because of not enough TUs - every other * case should be checked previously in this function. */ HUD_DisplayMessage(_("Can't perform action:\nnot enough TUs.\n")); } }
/** * @brief Performs end-of-turn processing. * @param[in] self Pointer to the event structure that is currently executed * @param[in] msg The netchannel message * @sa CL_EndRoundAnnounce */ void CL_DoEndRound (const eventRegister_t* self, dbuffer* msg) { /* hud changes */ if (cls.isOurRound()) UI_ExecuteConfunc("endround"); refdef.rendererFlags &= ~RDF_IRGOGGLES; /* change active player */ Com_Printf("Team %i ended round\n", cl.actTeam); cl.actTeam = NET_ReadByte(msg); Com_Printf("Team %i's round started!\n", cl.actTeam); /* hud changes */ if (cls.isOurRound()) { /* check whether a particle has to go */ CL_ParticleCheckRounds(); UI_ExecuteConfunc("startround"); HUD_DisplayMessage(_("Your round started!")); S_StartLocalSample("misc/roundstart", SND_VOLUME_DEFAULT); CL_ActorConditionalMoveCalc(selActor); } }
/** * @brief Revitalizes a stunned actor (all that is needed is the local entity state set). * @param[in] msg The netchannel message * @param[in] self Pointer to the event structure that is currently executed */ void CL_ActorRevitalised (const eventRegister_t* self, dbuffer* msg) { int entnum, state; NET_ReadFormat(msg, self->formatString, &entnum, &state); /* get les */ le_t* le = LE_Get(entnum); if (!le) LE_NotFoundError(entnum); if (!LE_IsStunned(le) && !LE_IsLivingActor(le)) Com_Error(ERR_DROP, "CL_ActorRevitalised: Can't revitalise, LE is not a dead or stunned actor"); LE_Lock(le); /* link any floor container into the actor temp floor container */ le_t* floor = LE_Find(ET_ITEM, le->pos); if (floor) le->setFloor(floor); le->state = state; /* play animation */ LE_SetThink(le, LET_StartIdle); /* Print some info. */ if (le->team == cls.team) { const character_t* chr = CL_ActorGetChr(le); if (chr) { char tmpbuf[128]; Com_sprintf(tmpbuf, lengthof(tmpbuf), _("%s was revitalised\n"), chr->name); HUD_DisplayMessage(tmpbuf); } } else { switch (le->team) { case (TEAM_CIVILIAN): HUD_DisplayMessage(_("A civilian was revitalised.")); break; case (TEAM_ALIEN): HUD_DisplayMessage(_("An alien was revitalised.")); break; case (TEAM_PHALANX): HUD_DisplayMessage(_("A soldier was revitalised.")); break; default: HUD_DisplayMessage(va(_("A member of team %i was revitalised."), le->team)); break; } } le->aabb.setMaxs(player_maxs); if (le->ptl) { CL_ParticleFree(le->ptl); le->ptl = nullptr; } /* add team members to the actor list */ CL_ActorAddToTeamList(le); /* update pathing as we maybe not can walk onto this actor anymore */ CL_ActorConditionalMoveCalc(selActor); LE_Unlock(le); }
/** * @brief Kills an actor (all that is needed is the local entity state set to STATE_DEAD). * @note Also changes the animation to a random death sequence and appends the dead animation * @param[in] msg The netchannel message * @param[in] self Pointer to the event structure that is currently executed */ void CL_ActorDie (const eventRegister_t *self, dbuffer *msg) { le_t *le; int entnum, state, playerNum; NET_ReadFormat(msg, self->formatString, &entnum, &state, &playerNum); /* get les */ le = LE_Get(entnum); if (!le) LE_NotFoundError(entnum); if (!LE_IsLivingActor(le)) Com_Error(ERR_DROP, "CL_ActorDie: Can't kill, LE is not an actor (type: %i)", le->type); if (!LE_IsStunned(le) && LE_IsDead(le)) Com_Error(ERR_DROP, "CL_ActorDie: Can't kill, actor already dead"); LE_Lock(le); /* set relevant vars */ FLOOR(le) = NULL; le->state = state; /* count spotted aliens */ cl.numEnemiesSpotted = CL_CountVisibleEnemies(); /* play animation */ LE_SetThink(le, NULL); R_AnimChange(&le->as, le->model1, va("death%i", LE_GetAnimationIndexForDeath(le))); R_AnimAppend(&le->as, le->model1, va("dead%i", LE_GetAnimationIndexForDeath(le))); /* Print some info about the death or stun. */ if (le->team == cls.team) { if (playerNum != le->pnum) { const char *playerName = CL_PlayerGetName(playerNum); char tmpbuf[128]; Com_sprintf(tmpbuf, lengthof(tmpbuf), _("%s lost a soldier\n"), playerName); HUD_DisplayMessage(tmpbuf); } else { const character_t *chr = CL_ActorGetChr(le); if (chr) { char tmpbuf[128]; if (LE_IsStunned(le)) { Com_sprintf(tmpbuf, lengthof(tmpbuf), _("%s was stunned\n"), chr->name); } else { Com_sprintf(tmpbuf, lengthof(tmpbuf), _("%s was killed\n"), chr->name); } HUD_DisplayMessage(tmpbuf); } } } else { switch (le->team) { case (TEAM_CIVILIAN): if (LE_IsStunned(le)) HUD_DisplayMessage(_("A civilian was stunned.")); else HUD_DisplayMessage(_("A civilian was killed.")); break; case (TEAM_ALIEN): if (LE_IsStunned(le)) HUD_DisplayMessage(_("An alien was stunned.")); else HUD_DisplayMessage(_("An alien was killed.")); break; case (TEAM_PHALANX): if (LE_IsStunned(le)) HUD_DisplayMessage(_("A soldier was stunned.")); else HUD_DisplayMessage(_("A soldier was killed.")); break; default: if (LE_IsStunned(le)) HUD_DisplayMessage(va(_("A member of team %i was stunned."), le->team)); else HUD_DisplayMessage(va(_("A member of team %i was killed."), le->team)); break; } } /** * @todo CHRSH_IsTeamDefRobot: spawn smoke particles for robots */ CL_ActorPlaySound(le, SND_DEATH); VectorCopy(player_dead_maxs, le->maxs); if (!LE_IsStunned(le)) le->contents = CONTENTS_DEADACTOR; CL_ActorRemoveFromTeamList(le); /* update pathing as we maybe can walk onto the dead actor now */ CL_ActorConditionalMoveCalc(selActor); LE_Unlock(le); }
/** * @sa CL_ActorAddToTeamList * @sa G_AppearPerishEvent * @sa CL_ActorAdd * @note EV_ACTOR_APPEAR */ void CL_ActorAppear (const eventRegister_t *self, struct dbuffer *msg) { le_t *le, *leResponsible; int entnum, entnumResponsible, modelnum1, modelnum2; int teamDefID = -1; /* check if the actor is already visible */ entnum = NET_ReadShort(msg); entnumResponsible = NET_ReadShort(msg); le = LE_Get(entnum); leResponsible = LE_Get(entnumResponsible); if (entnumResponsible != SKIP_LOCAL_ENTITY && !leResponsible) LE_NotFoundError(entnumResponsible); /* mission start - no actor is spawned yet - so create it */ if (!le) le = LE_Add(entnum); /* Locking should be unnecessary if CL_CheckDefault filters this call, since this event starts and * ends in this function only. Adding lock/unlock just to be sure. */ LE_Lock(le); /* maybe added via CL_ActorAdd before */ le->invis = false; /* get the info */ NET_ReadFormat(msg, self->formatString, &le->team, &teamDefID, &le->gender, &le->ucn, &le->pnum, &le->pos, &le->angle, &le->right, &le->left, &modelnum1, &modelnum2, &le->bodySkin, &le->headSkin, &le->state, &le->fieldSize, &le->maxTU, &le->maxMorale, &le->maxHP); if (teamDefID < 0 || teamDefID > csi.numTeamDefs) Com_Printf("CL_ActorAppear: Invalid teamDef index\n"); else le->teamDef = &csi.teamDef[teamDefID]; switch (le->fieldSize) { case ACTOR_SIZE_NORMAL: le->addFunc = CL_AddActor; le->type = ET_ACTOR; break; case ACTOR_SIZE_2x2: le->addFunc = CL_AddUGV; le->type = ET_ACTOR2x2; break; default: Com_Error(ERR_DROP, "Unknown fieldSize for le in CL_ActorAppear (EV_ACTOR_APPEAR)"); } le->modelnum1 = modelnum1; le->modelnum2 = modelnum2; le->model1 = LE_GetDrawModel(modelnum1); le->model2 = LE_GetDrawModel(modelnum2); Grid_PosToVec(cl.mapData->map, le->fieldSize, le->pos, le->origin); le->angles[YAW] = directionAngles[le->angle]; if (LE_IsDead(le) && !LE_IsStunned(le)) le->contents = CONTENTS_DEADACTOR; else le->contents = CONTENTS_ACTOR; VectorCopy(player_mins, le->mins); if (LE_IsDead(le)) VectorCopy(player_dead_maxs, le->maxs); else VectorCopy(player_maxs, le->maxs); LE_SetThink(le, LET_StartIdle); /* count spotted aliens (also stunned) */ cl.numEnemiesSpotted = CL_CountVisibleEnemies(); if (LE_IsLivingActor(le)) { if (cl.actTeam != cls.team) { /* center view (if wanted) */ LE_CenterView(le); } /* draw line of sight */ if (le->team != cls.team) { if (leResponsible) CL_DrawLineOfSight(leResponsible, le); /* message */ if (le->team != TEAM_CIVILIAN) { if (GAME_TeamIsKnown(le->teamDef)) { char tmpbuf[128]; Com_sprintf(tmpbuf, sizeof(tmpbuf), _("Enemy spotted: %s!"), _(le->teamDef->name)); HUD_DisplayMessage(tmpbuf); } else HUD_DisplayMessage(_("Unknown enemy spotted!")); } else HUD_DisplayMessage(_("Civilian spotted.")); /* update pathing as new actor could block path */ CL_ActorConditionalMoveCalc(leResponsible ? leResponsible : selActor); } } /* add team members to the actor list */ CL_ActorAddToTeamList(le); LE_Unlock(le); }