/** * @brief Applies morale behaviour on actors * @note only called when mor_panic is not zero * @sa G_MoralePanic * @sa G_MoraleRage * @sa G_MoraleStopRage * @sa G_MoraleStopPanic */ void G_MoraleBehaviour (int team) { bool enabled = G_IsMoraleEnabled(team); if (!enabled) return; Edict* ent = nullptr; while ((ent = G_EdictsGetNextLivingActorOfTeam(ent, team)) != nullptr) { /* this only applies to ET_ACTOR but not to ET_ACTOR2x2 */ if (ent->type != ET_ACTOR || CHRSH_IsTeamDefRobot(ent->chr.teamDef)) continue; /* if panic, determine what kind of panic happens: */ if (!G_IsPanicked(ent) && !G_IsRaged(ent)) { if (ent->morale <= mor_panic->integer) { const float ratio = (float) ent->morale / mor_panic->value; const bool sanity = ratio > (m_sanity->value * frand()); if (!sanity) G_SetInsane(ent); if (ratio > (m_rage->value * frand())) G_MoralePanic(ent); else G_MoraleRage(ent); /* if shaken, well .. be shaken; */ } else if (ent->morale <= mor_shaken->integer) { /* shaken is later reset along with reaction fire */ G_SetShaken(ent); G_ClientStateChange(ent->getPlayer(), ent, STATE_REACTION, false); G_EventSendState(G_VisToPM(ent->visflags), *ent); G_ClientPrintf(ent->getPlayer(), PRINT_HUD, _("%s is currently shaken."), ent->chr.name); G_PrintStats("%s is shaken (entnum %i).", ent->chr.name, ent->getIdNum()); } } else { if (G_IsPanicked(ent)) G_MoraleStopPanic(ent); else if (G_IsRaged(ent)) G_MoraleStopRage(ent); } G_ActorSetMaxs(ent); /* morale-regeneration, capped at max: */ int newMorale = ent->morale + MORALE_RANDOM(mor_regeneration->value); const int maxMorale = GET_MORALE(ent->chr.score.skills[ABILITY_MIND]); if (newMorale > maxMorale) ent->morale = maxMorale; else ent->morale = newMorale; /* send phys data and state: */ G_SendStats(*ent); } }
/** * @sa G_MoralePanic * @sa G_MoraleStopPanic * @sa G_MoraleStopRage * @sa G_MoraleBehaviour */ static void G_MoraleRage (edict_t * ent, qboolean sanity) { if (sanity) G_SetRage(ent); else G_SetInsane(ent); G_EventSendState(G_VisToPM(ent->visflags), ent); if (sanity) gi.BroadcastPrintf(PRINT_HUD, _("%s is on a rampage.\n"), ent->chr.name); else gi.BroadcastPrintf(PRINT_HUD, _("%s is consumed by mad rage!\n"), ent->chr.name); AI_ActorThink(G_PLAYER_FROM_ENT(ent), ent); }
/** * @sa G_MoralePanic * @sa G_MoraleStopPanic * @sa G_MoraleStopRage * @sa G_MoraleBehaviour */ static void G_MoraleRage (edict_t *ent, bool sanity) { if (sanity) { G_SetRage(ent); gi.BroadcastPrintf(PRINT_HUD, _("%s is on a rampage!"), ent->chr.name); G_PrintStats("%s is on a rampage (entnum %i).", ent->chr.name, ent->number); } else { G_SetInsane(ent); gi.BroadcastPrintf(PRINT_HUD, _("%s is consumed by mad rage!"), ent->chr.name); G_PrintStats("%s is consumed by mad rage (entnum %i).", ent->chr.name, ent->number); } G_EventSendState(G_VisToPM(ent->visflags), ent); AI_ActorThink(G_PLAYER_FROM_ENT(ent), ent); }
/** * @sa G_MoralePanic * @sa G_MoraleStopPanic * @sa G_MoraleStopRage * @sa G_MoraleBehaviour */ static void G_MoraleRage (Edict *ent, bool sanity) { if (sanity) { G_SetRage(ent); gi.BroadcastPrintf(PRINT_HUD, _("%s is on a rampage!"), ent->chr.name); G_PrintStats("%s is on a rampage (entnum %i).", ent->chr.name, ent->number); } else { G_SetInsane(ent); gi.BroadcastPrintf(PRINT_HUD, _("%s is consumed by mad rage!"), ent->chr.name); G_PrintStats("%s is consumed by mad rage (entnum %i).", ent->chr.name, ent->number); } G_EventSendState(G_VisToPM(ent->visflags), *ent); G_ClientStateChange(ent->getPlayer(), ent, ~STATE_REACTION, false); AI_ActorThink(ent->getPlayer(), ent); }