Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/act.movement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "act.hpp"

#include "ai.hpp"
#include "board.hpp"
#include "casting.hpp"
#include "charsize.hpp"
Expand Down Expand Up @@ -600,6 +601,10 @@ bool do_simple_move(CharData *ch, int dir, int need_specials_check) {
if (DECEASED(actor))
return true;

if (was_in != IN_ROOM(actor)) {
queue_glory_event(actor);
}

return true;
}

Expand Down Expand Up @@ -1734,7 +1739,7 @@ ACMD(do_drag) {
act("&3Your meditation is interrupted as %N grabs you.&0", false, ch, 0, 0, TO_CHAR);
if (IS_NPC(ch))
REMOVE_FLAG(MOB_FLAGS(ch), MOB_MEDITATE);
else
else
REMOVE_FLAG(PLR_FLAGS(ch), PLR_MEDITATE);
}

Expand Down
8 changes: 7 additions & 1 deletion src/ai.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "skills.hpp"
#include "structs.hpp"
#include "sysdep.hpp"
#include <vector>

#define MOB_ASSISTER(ch) \
(!MOB_FLAGGED((ch), MOB_PEACEFUL) && \
Expand All @@ -34,10 +35,15 @@ void perform_remove(CharData *ch, int pos);
int appraise_item(CharData *ch, ObjData *obj);
bool will_assist(CharData *ch, CharData *vict);
CharData *find_aggr_target(CharData *ch);
void glorion_distraction(CharData *ch, CharData *glorion);
int appraise_opponent(CharData *ch, CharData *vict);
bool is_aggr_to(CharData *ch, CharData *tch);

std::vector<CharData*> find_glorions(CharData* mob);
void glorion_distraction(CharData *ch, CharData *glorion);
void check_glory(CharData* ch, CharData* caster = nullptr);
void check_glory_around(CharData* ch);
void queue_glory_event(CharData* ch);

/* Class AI functions */
bool sorcerer_ai_action(CharData *ch, CharData *victim);
bool cleric_ai_action(CharData *ch, CharData *victim);
Expand Down
121 changes: 92 additions & 29 deletions src/ai_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -624,58 +624,80 @@ void glorion_distraction(CharData *ch, CharData *glorion) {
event_create(EVENT_QUICK_AGGRO, quick_aggro_event, mkgenericevent(ch, glorion, 0), true, &(ch->events), 0);
} else {
/* Glory wins: no attack. */
if (random_number(1, 8) == 1) {
if (true || random_number(1, 8) == 1) {
act("$n looks upon $N with awe in $s eyes.", true, ch, 0, glorion, TO_NOTVICT);
act("$n gazes at you in wonder.", true, ch, 0, glorion, TO_VICT);
act("You are distracted by $N's unearthly beauty.", true, ch, 0, glorion, TO_CHAR);
}
}
}

#define MAX_TARGETS 10
CharData *find_aggr_target(CharData *ch) {
CharData *tch;
struct aggr_target {
CharData *target;
int difficulty;
} targets[MAX_TARGETS + 1];
int i, j, k, num_targets, chosen_targets;

CharData *glorion = nullptr;
int glorion_count;
std::vector<CharData*> find_glorions(CharData* mob) {
std::vector<CharData*> glorions;
if (!mob || DECEASED(mob) || !IS_NPC(mob)) {
return glorions;
}

for (CharData* tch = world[IN_ROOM(mob)].people; tch; tch = tch->next_in_room) {
/* If there are any folks in the room with GLORY, they will
* interfere with aggression. One will be chosen at random,
* because there's a chance the mob will attack it. But no
* one else will be. */
if (mob != tch && CAN_SEE(mob, tch)) {
if (EFF_FLAGGED(tch, EFF_GLORY) && PLAYERALLY(tch)) {
glorions.push_back(tch);
}
}
}
return glorions;
}

static bool able_to_fight(CharData* ch, bool no_aggr_check = false) {
if (!ch || CH_NROOM(ch) == NOWHERE)
return nullptr;
return false;

if (ROOM_FLAGGED(CH_NROOM(ch), ROOM_PEACEFUL))
return nullptr;
return false;

if (!IS_NPC(ch) && !EFF_FLAGGED(ch, EFF_BERSERK)) {
if (!IS_NPC(ch) && !EFF_FLAGGED(ch, EFF_BERSERK) && !no_aggr_check) {
if (GET_WIMP_LEV(ch) >= GET_HIT(ch))
return nullptr;
return false;
if (GET_AGGR_LEV(ch) <= 0 || GET_AGGR_LEV(ch) > GET_HIT(ch))
return nullptr;
return false;
}

if (PLR_FLAGGED(ch, PLR_BOUND) || !AWAKE(ch) || EFF_FLAGGED(ch, EFF_MINOR_PARALYSIS) ||
EFF_FLAGGED(ch, EFF_MAJOR_PARALYSIS))
return false;

return true;
}

#define MAX_TARGETS 10
CharData *find_aggr_target(CharData *ch) {
CharData *tch;
struct aggr_target {
CharData *target;
int difficulty;
} targets[MAX_TARGETS + 1];
int i, j, k, num_targets, chosen_targets;

if (!able_to_fight(ch)) {
return nullptr;
}

/* Your intelligence determines how many targets you will evaluate. */
num_targets = std::max(1, GET_INT(ch) * MAX_TARGETS / 100);

/* Choose #num_targets characters at random */
glorion_count = 0;
for (i = 0, tch = world[IN_ROOM(ch)].people; tch; tch = tch->next_in_room) {
/* If there are any folks in the room with GLORY, they will
* interfere with aggression. One will be chosen at random,
* because there's a chance the mob will attack it. But no
* one else will be. */
* interfere with aggression. This check is only done the
* first time that a mob is exposed to the spell, so
* subsequent aggression checks should fail. */
if (ch != tch && CAN_SEE(ch, tch)) {
if (EFF_FLAGGED(tch, EFF_GLORY) && PLAYERALLY(tch)) {
glorion_count++;
if (random_number(1, glorion_count) == 1)
glorion = tch;
return nullptr;
} else if (is_aggr_to(ch, tch)) {
if (i >= num_targets)
j = random_number(0, i);
Expand All @@ -690,11 +712,6 @@ CharData *find_aggr_target(CharData *ch) {
}
}

if (glorion_count) {
glorion_distraction(ch, glorion);
return nullptr;
}

if (i == 0)
/* Didn't find anyone I was aggro to. */
return nullptr;
Expand Down Expand Up @@ -728,3 +745,49 @@ CharData *find_aggr_target(CharData *ch) {

return targets[k].target;
}

void check_glory(CharData* ch, CharData* caster) {
if (!able_to_fight(ch)) {
return;
}
std::vector<CharData*> glorions;
CharData* target = caster;
if (!caster) {
glorions = find_glorions(ch);
if (glorions.empty()) {
return;
}
target = glorions[random_number(0, glorions.size() - 1)];
}
glorion_distraction(ch, target);
}

void check_glory_around(CharData* ch) {
if (!able_to_fight(ch, true)) {
return;
}
for (CharData* tch = world[IN_ROOM(ch)].people; tch; tch = tch->next_in_room) {
if (!IS_NPC(tch)) {
continue;
}
check_glory(tch, ch);
}
}

EVENTFUNC(witness_glory_event) {
GenericEventData *data = (GenericEventData *)event_obj;
CharData *ch = data->ch;

if (EFF_FLAGGED(ch, EFF_GLORY)) {
check_glory_around(ch);
} else {
check_glory(ch);
}

return EVENT_FINISHED;
}

void queue_glory_event(CharData* ch) {
cancel_event(ch->events, EVENT_WITNESS_GLORY);
event_create(EVENT_WITNESS_GLORY, witness_glory_event, mkgenericevent(ch, nullptr, 0), true, &(ch->events), 1 RL_SEC);
}
1 change: 1 addition & 0 deletions src/events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const char *eventnames[MAX_EVENT + 1] = {"!INVALID EVENT!", /* 0 - reserved */
"command",
"start_editor",
"get_money", /* 30 */
"witness_glory",
"\n"};

/*************************************************************************/
Expand Down
3 changes: 2 additions & 1 deletion src/events.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,9 @@ void delayed_command(CharData *ch, char *command, int delay, bool repeatable);
#define EVENT_COMMAND 28
#define EVENT_EDITOR_START 29
#define EVENT_GET_MONEY 30
#define EVENT_WITNESS_GLORY 31
/* Update MAX_EVENT to be last event value + 1, please */
#define MAX_EVENT 31
#define MAX_EVENT 32

EVENTFUNC(extract_event);
EVENTFUNC(hurt_event);
Expand Down
5 changes: 5 additions & 0 deletions src/magic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "magic.hpp"

#include "ai.hpp"
#include "casting.hpp"
#include "chars.hpp"
#include "charsize.hpp"
Expand Down Expand Up @@ -3348,6 +3349,10 @@ int mag_affect(int skill, CharData *ch, CharData *victim, int spellnum, int save
if (to_char == nullptr && ch != victim)
act(to_room, false, ch, 0, victim, TO_CHAR);
}

if (spellnum == SPELL_GLORY) {
queue_glory_event(ch);
}
} else {
/* Add generic refresh message */
SkillDef *spell;
Expand Down