Skip to content

Instantly share code, notes, and snippets.

@y-ack
Last active July 18, 2022 07:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save y-ack/457dc3d34c93ce325c7c4afb4cb1cc93 to your computer and use it in GitHub Desktop.
Save y-ack/457dc3d34c93ce325c7c4afb4cb1cc93 to your computer and use it in GitHub Desktop.
i don't think we can 32183P our way out of this one, aifa.
# LAND MAKER ~ DAMAGE AND PUSHBACK [ywy] REV.1 2022/07/18
addresses apply for: landmakrj
## terminology:
'break' refers to a shot action that hits a piece on a corner,
causing them to disappear and send damage.
'placing' refers to a shot action that does not break.
'building' refers to pieces transformed into houses by a placing
shot action.
'pushback' refers to the behavior of the pusher retracting as a
result of breaking with specific damage output requirements met.
not to be confused with
'PUSHBACK' refers to an internal pusher state used by both item
arrows and 'pushback' as defined above.
## damage and pushback
### raw damage
raw damage for each piece is calculated at break time by $96680,
which runs once for each piece cleared, including the shot tile.
(larger structures count are a single 'piece')
non-building tiles (including items) are worth half a damage,
but they are counted separately from building damage, so that
leftover half-damage carries over between breaks.
single buildings are worth 1 damage,
structures are worth
`min(pusher_position, 7) * structure_level + structure_value`
where pusher position 0 is fully retracted and position 1 looks like
https://cdn.discordapp.com/attachments/455404849626873869/957277010512728104/32080.png
| | STRUCTURE | VALUE | HEX |
|0| bronze | 8 | 8h |
|1| silver | 22 | 16h |
|2| gold | 38 | 26h |
|3| platinum | 54 | 36h |
table: damage values by structure level [1]
e.g. breaking 2 silvers (structure level=1), at pusher position 2
adds
2*1 + 22
+ 2*1 + 22
for 48 raw damage from structures
note that 7 push is almost all the way down the board;
large structures will not be able to take advantage of it.
assuming one did break a gold structure at 5 push, 5*2 == 10 extra raw damage.
-------------------------------------------------------------------------------
[1] internal tile level assigns nonstructure `0` and bronze starting at 2,
but level used in structure damage is `(internal level - 2)` ($96696)
[2] pusher row is stored as index into board, div 16 for position here.
### damage conversion
$AB03E applies received damage
raw damage is converted into two types of damage
when it is sent to the opponent (represented by glowing orbs),
'piece damage' and 'push damage,'
but the conversion is affected by margin time.
the push damage conversion threshold starts at 9,
meaning 9 raw damage is needed for 1 push damage.
when the round elapsed time reaches 60 seconds,
the push damage threshold decreases by 1,
and further decreases every 30 seconds after that,
until a minimum push damage threshold of 4 (at 180 seconds) [1]
the remainder goes into piece damage, i.e.:
push damage += raw damage / push threshold
piece damage += raw damage % push threshold
in other words, <60s into a match, it takes 9 rawdmg for 1 push;
between 60 and 90s, 8 rawdmg is 1 push; and 180s+ is 4 dmg/push
note the modulo operator for nuisance tile damage:
remainder damage that doesn't go towards push goes into piece.
the push threshold influences nuisance tile accumulation!
if incoming push damage >= 3, the "DANGER" voice line plays.
-------------------------------------------------------------------------------
[1] (strictly speaking, this is a modifier that counts up and is subtracted
from 9 at damage conversion time, but a view of `(9 - modifier)` as
`push threshold` is simpler)
### pushback
pushback($953A4) is evaluated /whenever damage is sent/.
damage is sent on every frame that raw damage is >= 1.
(note that **all** breaks will send at least 1 damage;
breaking an item (0.5(shot tile)+0.5(item))
or single tile (0.5+0.5) will both evaluate pushback.)
internally, pushback accumulates raw damage sent.
it can be thought of like an invisible meter.
"pusher [position]" refers to the amount of board covered/topmost line
- when pusher is at 0, the meter resets.
- when pusher is NOT at 0,
- the requirement for pushback is `REQ[pusher] + 2`
- the total raw damage this frame is added to the total accumulated pushback
- if accumulated pushback meter exceeds the requirement:
- the threshold is subtracted for the meter
- the push state is set to PUSHBACK
| | REQ| +2 |
|0| 15 | 17 | (ignore this line when calculating)
|1| 15 | 17 |
|2| 13 | 15 |
|3| 9 | 11 |
|4| 6 | 8 |
|5| 4 | 6 |
|6| 2 | 4 |
|7| 1 | 3 |
|8| 1 | 3 |
|9| 1 | 3 |
table: pushback meter threshold lookup.
note that pusher 0 (and 9?) cannot actually be encountered.
- pusher 0 is fully retracted, and the threshold
is not considered if damage is sent at this position
- pusher 9 is off of the board.
for help visualizing pushback meter accumulation and requirements, see scripts for mame and fbneo:
https://gist.github.com/y-ack/b17cd4a25b673dcfc7303ad8f5c60770
#### example
given a pusher position of 2 and initial accumulated pushback
value of 0, a player makes two breaks: 1B+4, then 1S
at pusher 2, **15** raw damage is required to achieve pushback.
the first break, 1 bronze and 4 house pieces:
(2*0 + 8) + (4) = 12
12/15 is insufficient to trigger pushback
the second break, 1 silver:
(2*1 + 22) = 24
12 previously accumulated + 24 = 36
36/15 is sufficient to trigger pushback,
so pushback will occur this turn, and
(given that we have no incoming damage)
pusher position will be **1** for the next turn.
the pushback value vs requirement is now
21/17,
meaning the next shot that sends damage (any break) will also trigger pushback.
#### esoterics
fundamentally, the behavior of pushback is
"sending enough damage will retreat the pusher."
however, there are other subtle behaviors hidden in the already unexplained mechanic:
firstly, while every breaking shot will evaluate damage,
it is possible for damage to be counted over multiple frames.
the most obvious case is with **star items**, where the shot tile and item
are counted 40 frames before the tiles eliminated are counted.
additionally, it seems that there is some limit to the number of pieces
that can be counted while sweeping over the board each frame,
such that masses of single tiles send damage over multiple frames.
damage being evaluated on multiple frames means
pushback can be evaluated multiple times per break,
and because there is no check for whether pushback state has already occurred,
the pushback accumulator can drain multiple times with no benefit to the player.
this bug could be prevented by checking whether the push state is
already PUSHBACK before checking the pushback requirement.
similarly, because arrow items
1) activate on break
2) set the same PUSHBACK state,
breaking an arrow will drain pushback if possible, and unless there are
tiles in the danger zone, this is essentially 'wasted' pushback.
the second behavior has to do with pushback evaluation being triggered
by sending damage. this is another separation of the actions of
shooting a tile without sending damage (placing) and
shooting a tile and sending damage (breaking).
no matter how much pushback 'meter' is stored up,
the pusher cannot be repelled without making a breaking shot.
the other side of this is that pushback cannot be /drained/
without breaking tiles.
this includes the behavior of resetting when the pusher is fully retracted.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment