Skip to content

Commit

Permalink
Fix mirrored totem beckoning sometimes instakilling the player (tmewe…
Browse files Browse the repository at this point in the history
…tt#498)

This fixes the issue by reversing the bolt direction for the blinking triggered
by beckoning, by swapping the bolt origin and target and then reversing the
resulting list.

This also makes the same adjustment to the behavior of wands of beckoning. This
seems to make the wand's behavior more closely match what you'd expect from the
path displayed when targeting it. For instance, it makes it easier to target
enemies that are behind other enemies.
  • Loading branch information
nstoddard authored Jan 16, 2023
1 parent 31ced99 commit 1505d71
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 9 deletions.
1 change: 1 addition & 0 deletions changes/beckoning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed that mirrored totem beckoning could instakill the player in some situations, and modified the wand of beckoning to more easily target enemies behind obstacles.
2 changes: 1 addition & 1 deletion src/brogue/Combat.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ boolean forceWeaponHit(creature *defender, item *theItem) {
}
theBolt = boltCatalog[BOLT_BLINKING];
theBolt.magnitude = max(1, netEnchant(theItem) / FP_FACTOR);
zap(oldLoc, newLoc, &theBolt, false);
zap(oldLoc, newLoc, &theBolt, false, false);
if (!(defender->bookkeepingFlags & MB_IS_DYING)
&& distanceBetween(oldLoc.x, oldLoc.y, defender->loc.x, defender->loc.y) > 0
&& distanceBetween(oldLoc.x, oldLoc.y, defender->loc.x, defender->loc.y) < weaponForceDistance(netEnchant(theItem))) {
Expand Down
36 changes: 32 additions & 4 deletions src/brogue/Items.c
Original file line number Diff line number Diff line change
Expand Up @@ -4241,7 +4241,7 @@ void beckonMonster(creature *monst, short x, short y) {
pos from = monst->loc;
pos to = (pos){ .x = x, .y = y };
theBolt.magnitude = max(1, (distanceBetween(x, y, monst->loc.x, monst->loc.y) - 2) / 2);
zap(from, to, &theBolt, false);
zap(from, to, &theBolt, false, true);
if (monst->ticksUntilTurn < player.attackSpeed+1) {
monst->ticksUntilTurn = player.attackSpeed+1;
}
Expand Down Expand Up @@ -4713,7 +4713,7 @@ void detonateBolt(bolt *theBolt, creature *caster, short x, short y, boolean *au
}

// returns whether the bolt effect should autoID any staff or wand it came from, if it came from a staff or wand
boolean zap(pos originLoc, pos targetLoc, bolt *theBolt, boolean hideDetails) {
boolean zap(pos originLoc, pos targetLoc, bolt *theBolt, boolean hideDetails, boolean reverseBoltDir) {
pos listOfCoordinates[MAX_BOLT_LENGTH];
short i, j, k, x, y, x2, y2, numCells, blinkDistance = 0, boltLength, initialBoltLength, lights[DCOLS][DROWS][3];
creature *monst = NULL, *shootingMonst;
Expand Down Expand Up @@ -4741,7 +4741,34 @@ boolean zap(pos originLoc, pos targetLoc, bolt *theBolt, boolean hideDetails) {
y = originLoc.y;

initialBoltLength = boltLength = 5 * theBolt->magnitude;
numCells = getLineCoordinates(listOfCoordinates, originLoc, targetLoc, (hideDetails ? &boltCatalog[BOLT_NONE] : theBolt));
if (reverseBoltDir) {
// Beckoning (from mirrored totems and the wand) is implemented as two bolts, one going from
// the totem/player to the target, and another from the target back to the source, to blink
// them adjacent. However, bolt paths are asymmetric; the path from A to B isn't necessarily
// the same as the path from B to A. If the second bolt (the blink) follows a different
// path, it's possible for the target not to be blinked all the way back to the source
// because it hits an obstacle (usually a monster). This results in issue #497, as well as
// unintuitive behavior for the wand of beckoning. As a workaround, for the second bolt, we
// compute it as if it went from the source to the target, and then reverse the list of
// coordinates. This ensures that the two bolts will include exactly the same coordinates,
// so the target won't get stuck on any obstacles while being beckoned.
pos listOfCoordinatesTmp[MAX_BOLT_LENGTH];
short numCellsTmp = getLineCoordinates(listOfCoordinatesTmp, targetLoc, originLoc, (hideDetails ? &boltCatalog[BOLT_NONE] : theBolt));
numCells = -1;
for (int i = 0; i < numCellsTmp; i++) {
if (listOfCoordinatesTmp[i].x == originLoc.x && listOfCoordinatesTmp[i].y == originLoc.y) {
numCells = i+1;
break;
}
}
brogueAssert(numCells > -1);
for (int i = 0; i < numCells-1; i++) {
listOfCoordinates[i] = listOfCoordinatesTmp[numCells-2-i];
}
listOfCoordinates[numCells-1] = targetLoc;
} else {
numCells = getLineCoordinates(listOfCoordinates, originLoc, targetLoc, (hideDetails ? &boltCatalog[BOLT_NONE] : theBolt));
}
shootingMonst = monsterAtLoc(originLoc.x, originLoc.y);

if (hideDetails) {
Expand Down Expand Up @@ -6412,7 +6439,8 @@ boolean useStaffOrWand(item *theItem, boolean *commandsRecorded) {
if (theItem->charges > 0) {
autoID = zap(originLoc, zapTarget,
&theBolt,
!boltKnown); // hide bolt details
!boltKnown, // hide bolt details
false);
if (autoID) {
if (!tableForItemCategory(theItem->category)[theItem->kind].identified) {
itemName(theItem, buf2, false, false, NULL);
Expand Down
4 changes: 2 additions & 2 deletions src/brogue/Monsters.c
Original file line number Diff line number Diff line change
Expand Up @@ -2339,7 +2339,7 @@ boolean monsterBlinkToPreferenceMap(creature *monst, short **preferenceMap, bool
}
monst->ticksUntilTurn = monst->attackSpeed * (monst->info.flags & MONST_CAST_SPELLS_SLOWLY ? 2 : 1);
theBolt = boltCatalog[theBoltType];
zap(origin, bestTarget, &theBolt, false);
zap(origin, bestTarget, &theBolt, false, false);
return true;
}
return false;
Expand Down Expand Up @@ -2677,7 +2677,7 @@ void monsterCastSpell(creature *caster, creature *target, enum boltType boltInde
theBolt = boltCatalog[boltIndex];
pos originLoc = caster->loc;
pos targetLoc = target->loc;
zap(originLoc, targetLoc, &theBolt, false);
zap(originLoc, targetLoc, &theBolt, false, false);

if (player.currentHP <= 0) {
gameOver(monsterCatalog[caster->info.monsterID].monsterName, false);
Expand Down
2 changes: 1 addition & 1 deletion src/brogue/Movement.c
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ boolean handleWhipAttacks(creature *attacker, enum directions dir, boolean *abor
attacker->bookkeepingFlags &= ~MB_SUBMERGED;
theBolt = boltCatalog[BOLT_WHIP];
theBolt.theChar = boltChar[dir];
zap(originLoc, targetLoc, &theBolt, false);
zap(originLoc, targetLoc, &theBolt, false, false);
return true;
}
return false;
Expand Down
2 changes: 1 addition & 1 deletion src/brogue/Rogue.h
Original file line number Diff line number Diff line change
Expand Up @@ -3062,7 +3062,7 @@ extern "C" {
void checkForMissingKeys(short x, short y);
enum boltEffects boltEffectForItem(item *theItem);
enum boltType boltForItem(item *theItem);
boolean zap(pos originLoc, pos targetLoc, bolt *theBolt, boolean hideDetails);
boolean zap(pos originLoc, pos targetLoc, bolt *theBolt, boolean hideDetails, boolean reverseBoltDir);
boolean nextTargetAfter(short *returnX,
short *returnY,
short targetX,
Expand Down

0 comments on commit 1505d71

Please sign in to comment.