/** * @brief Change the animation of an actor to the idle animation (which can be * panic, dead or stand) * @note We have more than one animation for dead - the index is given by the * state of the local entity * @note Think function * @note See the *.anm files in the models dir */ void LET_StartIdle (le_t* le) { /* hidden actors don't have models assigned, thus we can not change the * animation for any model */ if (!LE_IsInvisible(le)) { if (LE_IsDead(le)) R_AnimChange(&le->as, le->model1, va("dead%i", LE_GetAnimationIndexForDeath(le))); else if (LE_IsPanicked(le)) R_AnimChange(&le->as, le->model1, "panic0"); else R_AnimChange(&le->as, le->model1, LE_GetAnim("stand", le->right, le->left, le->state)); } le->pathPos = le->pathLength = 0; if (le->stepList != nullptr) { leStep_t* step = le->stepList->next; Mem_Free(le->stepList); le->stepList = step; if (step != nullptr) { le->stepIndex--; } else if (le->stepIndex != 0) { Com_Error(ERR_DROP, "stepindex for entnum %i is out of sync (%i should be 0)\n", le->entnum, le->stepIndex); } } /* keep this animation until something happens */ LE_SetThink(le, nullptr); }
/** * @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); }