Skip to content

Commit

Permalink
Resurrect phoenix eggs, phylacteries and vampires (#642)
Browse files Browse the repository at this point in the history
  • Loading branch information
zenzombie authored Jan 22, 2024
1 parent ec2e49d commit 888f86f
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 46 deletions.
1 change: 1 addition & 0 deletions changes/phoenix-resurrection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Resurrection altars now function differently for phoenixes and liches. The phoenix egg or phylactery will be revived instead, and the ability to turn into a phoenix or lich restored. Similarly, a vampire's ability to spawn vampire bats will be restored. Monsters that are summoned by allies (furies, phantoms, vampire bats) are no longer eligible for resurrection. Only the summoner will be resurrected. Also, destroying a phoenix egg or phylactery now counts toward weapon auto-id.
5 changes: 3 additions & 2 deletions src/brogue/Combat.c
Original file line number Diff line number Diff line change
Expand Up @@ -1208,7 +1208,7 @@ boolean attack(creature *attacker, creature *defender, boolean lungeAttack) {

if (attacker == &player
&& (defender->bookkeepingFlags & MB_IS_DYING)
&& (defender->bookkeepingFlags & MB_HAS_SOUL)) {
&& (defender->bookkeepingFlags & MB_WEAPON_AUTO_ID)) {

decrementWeaponAutoIDTimer();
}
Expand Down Expand Up @@ -1663,7 +1663,8 @@ void killCreature(creature *decedent, boolean administrativeDeath) {
if (!administrativeDeath
&& decedent->creatureState == MONSTER_ALLY
&& !canSeeMonster(decedent)
&& !(decedent->info.flags & MONST_INANIMATE)
&& (!(decedent->info.flags & MONST_INANIMATE)
|| (monsterCatalog[decedent->info.monsterID].abilityFlags & MA_ENTER_SUMMONS))
&& !(decedent->bookkeepingFlags & MB_BOUND_TO_LEADER)
&& !decedent->carriedMonster) {

Expand Down
2 changes: 1 addition & 1 deletion src/brogue/GlobalsBase.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const gameConstants *gameConst;
int gameVariant = VARIANT_BROGUE;
creatureList *monsters;
creatureList *dormantMonsters;
creatureList purgatory;
creatureList purgatory; // used to hold dead allies awaiting resurrection
item *floorItems;
item *packItems;
item *monsterItemsHopper;
Expand Down
16 changes: 1 addition & 15 deletions src/brogue/Items.c
Original file line number Diff line number Diff line change
Expand Up @@ -3819,21 +3819,7 @@ boolean polymorph(creature *monst) {
monst->attackSpeed *= 2;
}
monst->wasNegated = false;
clearStatus(monst);

if (monst->info.flags & MONST_FIERY) {
monst->status[STATUS_BURNING] = monst->maxStatus[STATUS_BURNING] = 1000; // won't decrease
}
if (monst->info.flags & MONST_FLIES) {
monst->status[STATUS_LEVITATING] = monst->maxStatus[STATUS_LEVITATING] = 1000; // won't decrease
}
if (monst->info.flags & MONST_IMMUNE_TO_FIRE) {
monst->status[STATUS_IMMUNE_TO_FIRE] = monst->maxStatus[STATUS_IMMUNE_TO_FIRE] = 1000; // won't decrease
}
if (monst->info.flags & MONST_INVISIBLE) {
monst->status[STATUS_INVISIBLE] = monst->maxStatus[STATUS_INVISIBLE] = 1000; // won't decrease
}
monst->status[STATUS_NUTRITION] = monst->maxStatus[STATUS_NUTRITION] = 1000;
initializeStatus(monst);

if (monst->bookkeepingFlags & MB_CAPTIVE) {
demoteMonsterFromLeadership(monst);
Expand Down
50 changes: 31 additions & 19 deletions src/brogue/Monsters.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ creature *generateMonster(short monsterID, boolean itemPossible, boolean mutatio
const int POW_DEEP_MUTATION[] = {11, 13, 16, 18, 21, 25, 30, 35, 41, 48, 56, 65, 76};

creature *monst = calloc(1, sizeof(creature));
clearStatus(monst);
monst->info = monsterCatalog[monsterID];
initializeStatus(monst);

monst->mutationIndex = -1;
if (mutationPossible
Expand Down Expand Up @@ -118,20 +118,6 @@ creature *generateMonster(short monsterID, boolean itemPossible, boolean mutatio
monst->waypointAlreadyVisited[i] = rand_range(0, 1);
}

if (monst->info.flags & MONST_FIERY) {
monst->status[STATUS_BURNING] = monst->maxStatus[STATUS_BURNING] = 1000; // won't decrease
}
if (monst->info.flags & MONST_FLIES) {
monst->status[STATUS_LEVITATING] = monst->maxStatus[STATUS_LEVITATING] = 1000; // won't decrease
}
if (monst->info.flags & MONST_IMMUNE_TO_FIRE) {
monst->status[STATUS_IMMUNE_TO_FIRE] = monst->maxStatus[STATUS_IMMUNE_TO_FIRE] = 1000; // won't decrease
}
if (monst->info.flags & MONST_INVISIBLE) {
monst->status[STATUS_INVISIBLE] = monst->maxStatus[STATUS_INVISIBLE] = 1000; // won't decrease
}
monst->status[STATUS_NUTRITION] = monst->maxStatus[STATUS_NUTRITION] = 1000;

if (monst->info.flags & MONST_CARRY_ITEM_100) {
itemChance = 100;
} else if (monst->info.flags & MONST_CARRY_ITEM_25) {
Expand All @@ -156,8 +142,8 @@ creature *generateMonster(short monsterID, boolean itemPossible, boolean mutatio

initializeGender(monst);

if (!(monst->info.flags & MONST_INANIMATE) && !monst->status[STATUS_LIFESPAN_REMAINING]) {
monst->bookkeepingFlags |= MB_HAS_SOUL;
if (!(monst->info.flags & MONST_INANIMATE) || (monst->info.abilityFlags & MA_ENTER_SUMMONS)) {
monst->bookkeepingFlags |= MB_WEAPON_AUTO_ID;
}

return monst;
Expand Down Expand Up @@ -543,7 +529,7 @@ creature *cloneMonster(creature *monst, boolean announce, boolean placeClone) {
newMonst->carriedMonster = NULL; // Temporarily remove anything it's carrying.

initializeGender(newMonst);
newMonst->bookkeepingFlags &= ~(MB_LEADER | MB_CAPTIVE | MB_HAS_SOUL);
newMonst->bookkeepingFlags &= ~(MB_LEADER | MB_CAPTIVE | MB_WEAPON_AUTO_ID);
newMonst->bookkeepingFlags |= MB_FOLLOWER;
newMonst->mapToMe = NULL;
newMonst->safetyMap = NULL;
Expand Down Expand Up @@ -711,6 +697,9 @@ boolean spawnMinions(short hordeID, creature *leader, boolean summoned, boolean
monst->bookkeepingFlags |= (MB_FOLLOWER | MB_JUST_SUMMONED);
monst->leader = leader;
monst->creatureState = leader->creatureState;
if (monst->creatureState == MONSTER_ALLY) {
monst->bookkeepingFlags |= MB_DOES_NOT_RESURRECT;
}
monst->mapToMe = NULL;
if (theHorde->flags & HORDE_DIES_ON_LEADER_DEATH) {
monst->bookkeepingFlags |= MB_BOUND_TO_LEADER;
Expand Down Expand Up @@ -2828,6 +2817,13 @@ boolean resurrectAlly(const pos loc) {
monToRaise->status[STATUS_DISCORDANT] = 0;
heal(monToRaise, 100, true);

// put humpty dumpty back together again. special handling for phoenix egg, phylactery, vampire
if (monsterCatalog[monToRaise->info.monsterID].abilityFlags & MA_ENTER_SUMMONS) {
monToRaise->info = monsterCatalog[monToRaise->info.monsterID];
initializeStatus(monToRaise);
monToRaise->wasNegated = false;
}

return true;
} else {
return false;
Expand Down Expand Up @@ -3788,12 +3784,28 @@ boolean moveMonster(creature *monst, short dx, short dy) {
return false;
}

void clearStatus(creature *monst) {
/// @brief initialize a creature's status effects to the default values
/// @param monst the creature
void initializeStatus(creature *monst) {
short i;

for (i=0; i<NUMBER_OF_STATUS_EFFECTS; i++) {
monst->status[i] = monst->maxStatus[i] = 0;
}

if (monst->info.flags & MONST_FIERY) {
monst->status[STATUS_BURNING] = monst->maxStatus[STATUS_BURNING] = 1000; // won't decrease
}
if (monst->info.flags & MONST_FLIES) {
monst->status[STATUS_LEVITATING] = monst->maxStatus[STATUS_LEVITATING] = 1000; // won't decrease
}
if (monst->info.flags & MONST_IMMUNE_TO_FIRE) {
monst->status[STATUS_IMMUNE_TO_FIRE] = monst->maxStatus[STATUS_IMMUNE_TO_FIRE] = 1000; // won't decrease
}
if (monst->info.flags & MONST_INVISIBLE) {
monst->status[STATUS_INVISIBLE] = monst->maxStatus[STATUS_INVISIBLE] = 1000; // won't decrease
}
monst->status[STATUS_NUTRITION] = monst->maxStatus[STATUS_NUTRITION] = (monst == &player ? STOMACH_SIZE : 1000);
}

// Bumps a creature to a random nearby hospitable cell.
Expand Down
9 changes: 5 additions & 4 deletions src/brogue/Rogue.h
Original file line number Diff line number Diff line change
Expand Up @@ -2088,7 +2088,7 @@ enum monsterAbilityFlags {
MA_HIT_HALLUCINATE = Fl(0), // monster can hit to cause hallucinations
MA_HIT_STEAL_FLEE = Fl(1), // monster can steal an item and then run away
MA_HIT_BURN = Fl(2), // monster can hit to set you on fire
MA_ENTER_SUMMONS = Fl(3), // monster will "become" its summoned leader, reappearing when that leader is defeated
MA_ENTER_SUMMONS = Fl(3), // monster will "become" its summoned leader, reappearing when that leader is defeated (phylactery, phoenix egg, vampire)
MA_HIT_DEGRADE_ARMOR = Fl(4), // monster damages armor
MA_CAST_SUMMON = Fl(5), // requires that there be one or more summon hordes with this monster type as the leader
MA_SEIZES = Fl(6), // monster seizes enemies before attacking
Expand Down Expand Up @@ -2136,10 +2136,11 @@ enum monsterBookkeepingFlags {
MB_IS_DYING = Fl(19), // monster is currently dying; the death is still being processed
MB_GIVEN_UP_ON_SCENT = Fl(20), // to help the monster remember that the scent map is a dead end
MB_IS_DORMANT = Fl(21), // lurking, waiting to burst out
MB_HAS_SOUL = Fl(22), // slaying the monster will count toward weapon auto-ID
MB_WEAPON_AUTO_ID = Fl(22), // slaying the monster will count toward weapon auto-ID
MB_ALREADY_SEEN = Fl(23), // seeing this monster won't interrupt exploration
MB_ADMINISTRATIVE_DEATH = Fl(24), // like the `administrativeDeath` parameter to `killCreature`
MB_HAS_DIED = Fl(25) // monster has already been killed but not yet removed from `monsters`
MB_HAS_DIED = Fl(25), // monster has already been killed but not yet removed from `monsters`
MB_DOES_NOT_RESURRECT = Fl(26) // resurrection altars don't revive monsters summoned by allies
};

// Defines all creatures, which include monsters and the player:
Expand Down Expand Up @@ -3147,7 +3148,7 @@ extern "C" {
void monstersTurn(creature *monst);
boolean getRandomMonsterSpawnLocation(short *x, short *y);
void spawnPeriodicHorde();
void clearStatus(creature *monst);
void initializeStatus(creature *monst);
void moralAttack(creature *attacker, creature *defender);
short runicWeaponChance(item *theItem, boolean customEnchantLevel, fixpt enchantLevel);
void magicWeaponHit(creature *defender, item *theItem, boolean backstabbed);
Expand Down
11 changes: 6 additions & 5 deletions src/brogue/RogueMain.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,9 +334,8 @@ void initializeRogue(uint64_t seed) {
initializeGender(&player);
player.movementSpeed = player.info.movementSpeed;
player.attackSpeed = player.info.attackSpeed;
clearStatus(&player);
initializeStatus(&player);
player.carriedItem = NULL;
player.status[STATUS_NUTRITION] = player.maxStatus[STATUS_NUTRITION] = STOMACH_SIZE;
player.currentHP = player.info.maxHP;
player.creatureState = MONSTER_ALLY;
player.ticksUntilTurn = 0;
Expand Down Expand Up @@ -905,13 +904,15 @@ static void removeDeadMonstersFromList(creatureList *list) {
if (decedent->bookkeepingFlags & MB_HAS_DIED) {
removeCreature(list, decedent);
if (decedent->leader == &player
&& !(decedent->info.flags & MONST_INANIMATE)
&& (decedent->bookkeepingFlags & MB_HAS_SOUL)
&& !(decedent->bookkeepingFlags & MB_DOES_NOT_RESURRECT)
&& (!(decedent->info.flags & MONST_INANIMATE)
|| (monsterCatalog[decedent->info.monsterID].abilityFlags & MA_ENTER_SUMMONS))
&& (decedent->bookkeepingFlags & MB_WEAPON_AUTO_ID)
&& !(decedent->bookkeepingFlags & MB_ADMINISTRATIVE_DEATH)) {

// Unset flag, since the purgatory list should be iterable.
decedent->bookkeepingFlags &= ~MB_HAS_DIED;
prependCreature(&purgatory, decedent);
prependCreature(&purgatory, decedent); // add for possible future resurrection
} else {
freeCreature(decedent);
}
Expand Down

0 comments on commit 888f86f

Please sign in to comment.