Skip to content

Commit

Permalink
Merge pull request #700 from zenzombie/bugfix-paralysis-runic
Browse files Browse the repository at this point in the history
Fixes #699
  • Loading branch information
tmewett committed Jul 3, 2024
2 parents b68f5a3 + f9f27c0 commit 225353e
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 46 deletions.
99 changes: 53 additions & 46 deletions src/brogue/Combat.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,16 +164,63 @@ static void addMonsterToContiguousMonsterGrid(short x, short y, creature *monst,
}
}

static short alliedCloneCount(creature *monst) {
short count = 0;
for (creatureIterator it = iterateCreatures(monsters); hasNextCreature(it);) {
creature *temp = nextCreature(&it);
if (temp != monst
&& temp->info.monsterID == monst->info.monsterID
&& monstersAreTeammates(temp, monst)) {

count++;
}
}
if (rogue.depthLevel > 1) {
for (creatureIterator it = iterateCreatures(&levels[rogue.depthLevel - 2].monsters); hasNextCreature(it);) {
creature *temp = nextCreature(&it);
if (temp != monst
&& temp->info.monsterID == monst->info.monsterID
&& monstersAreTeammates(temp, monst)) {

count++;
}
}
}
if (rogue.depthLevel < gameConst->deepestLevel) {
for (creatureIterator it = iterateCreatures(&levels[rogue.depthLevel].monsters); hasNextCreature(it);) {
creature *temp = nextCreature(&it);
if (temp != monst
&& temp->info.monsterID == monst->info.monsterID
&& monstersAreTeammates(temp, monst)) {

count++;
}
}
}
return count;
}

// Splits a monster in half.
// The split occurs only if there is a spot adjacent to the contiguous
// group of monsters that the monster would not avoid.
// The contiguous group is supplemented with the given (x, y) coordinates, if any;
// this is so that jellies et al. can spawn behind the player in a hallway.
static void splitMonster(creature *monst, pos loc) {
void splitMonster(creature *monst, creature *attacker) {
char buf[DCOLS * 3];
char monstName[DCOLS];
char monsterGrid[DCOLS][DROWS], eligibleGrid[DCOLS][DROWS];
creature *clone;
pos loc = INVALID_POS;

if ((monst->info.abilityFlags & MA_CLONE_SELF_ON_DEFEND) && alliedCloneCount(monst) < 100
&& monst->currentHP > 0 && !(monst->bookkeepingFlags & MB_IS_DYING)) {

if (distanceBetween(monst->loc, attacker->loc) <= 1) {
loc = attacker->loc;
}
} else {
return;
}

zeroOutGrid(monsterGrid);
zeroOutGrid(eligibleGrid);
Expand Down Expand Up @@ -264,42 +311,6 @@ static void splitMonster(creature *monst, pos loc) {
}
}

static short alliedCloneCount(creature *monst) {
short count = 0;
for (creatureIterator it = iterateCreatures(monsters); hasNextCreature(it);) {
creature *temp = nextCreature(&it);
if (temp != monst
&& temp->info.monsterID == monst->info.monsterID
&& monstersAreTeammates(temp, monst)) {

count++;
}
}
if (rogue.depthLevel > 1) {
for (creatureIterator it = iterateCreatures(&levels[rogue.depthLevel - 2].monsters); hasNextCreature(it);) {
creature *temp = nextCreature(&it);
if (temp != monst
&& temp->info.monsterID == monst->info.monsterID
&& monstersAreTeammates(temp, monst)) {

count++;
}
}
}
if (rogue.depthLevel < gameConst->deepestLevel) {
for (creatureIterator it = iterateCreatures(&levels[rogue.depthLevel].monsters); hasNextCreature(it);) {
creature *temp = nextCreature(&it);
if (temp != monst
&& temp->info.monsterID == monst->info.monsterID
&& monstersAreTeammates(temp, monst)) {

count++;
}
}
}
return count;
}

// This function is called whenever one creature acts aggressively against another in a way that directly causes damage.
// This can be things like melee attacks, fire/lightning attacks or throwing a weapon.
void moralAttack(creature *attacker, creature *defender) {
Expand Down Expand Up @@ -336,14 +347,6 @@ void moralAttack(creature *attacker, creature *defender) {

alertMonster(defender); // this alerts the monster that you're nearby
}

if ((defender->info.abilityFlags & MA_CLONE_SELF_ON_DEFEND) && alliedCloneCount(defender) < 100) {
if (distanceBetween(defender->loc, attacker->loc) <= 1) {
splitMonster(defender, attacker->loc);
} else {
splitMonster(defender, INVALID_POS);
}
}
}
}

Expand Down Expand Up @@ -556,6 +559,7 @@ static boolean forceWeaponHit(creature *defender, item *theItem) {
}
}
moralAttack(&player, defender);
splitMonster(defender, &player);

if (otherMonster
&& !(defender->info.flags & (MONST_IMMUNE_TO_WEAPONS | MONST_INVULNERABLE))) {
Expand All @@ -577,6 +581,7 @@ static boolean forceWeaponHit(creature *defender, item *theItem) {
if (otherMonster->creatureState != MONSTER_ALLY) {
// Allies won't defect if you throw another monster at them, even though it hurts.
moralAttack(&player, otherMonster);
splitMonster(defender, &player);
}
}
}
Expand Down Expand Up @@ -1216,11 +1221,13 @@ boolean attack(creature *attacker, creature *defender, boolean lungeAttack) {
}
}

moralAttack(attacker, defender);

if (attacker == &player && rogue.weapon && (rogue.weapon->flags & ITEM_RUNIC)) {
magicWeaponHit(defender, rogue.weapon, sneakAttack || defenderWasAsleep || defenderWasParalyzed);
}

moralAttack(attacker, defender);
splitMonster(defender, attacker);

if (attacker == &player
&& (defender->bookkeepingFlags & MB_IS_DYING)
Expand Down
2 changes: 2 additions & 0 deletions src/brogue/Items.c
Original file line number Diff line number Diff line change
Expand Up @@ -4446,6 +4446,7 @@ static boolean updateBolt(bolt *theBolt, creature *caster, short x, short y,
if (!alreadyReflected
|| caster != &player) {
moralAttack(caster, monst);
splitMonster(monst, caster);
}
}
if (theBolt->flags & BF_FIERY) {
Expand Down Expand Up @@ -6053,6 +6054,7 @@ static boolean hitMonsterWithProjectileWeapon(creature *thrower, creature *monst
messageWithColor(buf, messageColorFromVictim(monst), 0);
}
moralAttack(thrower, monst);
splitMonster(monst, thrower);
if (armorRunicString[0]) {
message(armorRunicString, 0);
}
Expand Down
1 change: 1 addition & 0 deletions src/brogue/Rogue.h
Original file line number Diff line number Diff line change
Expand Up @@ -3205,6 +3205,7 @@ extern "C" {
void initializeStatus(creature *monst);
void handlePaladinFeat(creature *defender);
void moralAttack(creature *attacker, creature *defender);
void splitMonster(creature *monst, creature *attacker);
short runicWeaponChance(item *theItem, boolean customEnchantLevel, fixpt enchantLevel);
void magicWeaponHit(creature *defender, item *theItem, boolean backstabbed);
void disentangle(creature *monst);
Expand Down

0 comments on commit 225353e

Please sign in to comment.