Clone: Difference between revisions
Content added Content deleted
Piranhaplant (talk | contribs) No edit summary |
Piranhaplant (talk | contribs) No edit summary |
||
Line 38: | Line 38: | ||
{| class="wikitable" |
{| class="wikitable" |
||
|- |
|- |
||
! Address !! Length !! [[Data types|Type]] !! Description |
! Address !! Length !! [[Data types|Type]] !! Name !! Description |
||
|- |
|- |
||
| $00 || 2 || int16 || X position |
| $00 || 2 || int16 || x || X position |
||
|- |
|- |
||
| $02 || 2 || int16 || Y position |
| $02 || 2 || int16 || y || Y position |
||
|} |
|} |
||
Line 49: | Line 49: | ||
{| class="wikitable" |
{| class="wikitable" |
||
|- |
|- |
||
! Address !! Length !! [[Data types|Type]] !! Description |
! Address !! Length !! [[Data types|Type]] !! Name !! Description |
||
|- |
|- |
||
| $08 || 2 || pointer16 || Pointer to sprite |
| $08 || 2 || pointer16 || sprite || Pointer to sprite |
||
|- |
|- |
||
| $0A || 2 || uint16 || Number of frames until next animation frame |
| $0A || 2 || uint16 || framesUntilAnimUpdate || Number of frames until next animation frame |
||
|- |
|- |
||
| $0C || 2 || uint16 || Current animation frame (x2 during spawn animation) |
| $0C || 2 || uint16 || animationFrame || Current animation frame (x2 during spawn animation) |
||
|- |
|- |
||
| $0E || 2 || direction || Current direction |
| $0E || 2 || direction || direction || Current direction |
||
|- |
|- |
||
| $10 || 2 || unused || Unused |
| $10 || 2 || unused || || Unused |
||
|- |
|- |
||
| $12 || 2 || int16 || X position in pixels (derived from $16) |
| $12 || 2 || int16 || xPixels || X position in pixels (derived from $16) |
||
|- |
|- |
||
| $14 || 2 || int16 || Y position in pixels (derived from $18) |
| $14 || 2 || int16 || yPixels || Y position in pixels (derived from $18) |
||
|- |
|- |
||
| $16 || 2 || int16 x4 || X position |
| $16 || 2 || int16 x4 || x || X position |
||
|- |
|- |
||
| $18 || 2 || int16 x4 || Y position |
| $18 || 2 || int16 x4 || y || Y position |
||
|- |
|- |
||
| $1A || 2 || int16 || New X position in pixels |
| $1A || 2 || int16 || newXPixels || New X position in pixels |
||
|- |
|- |
||
| $1C || 2 || int16 || New Y position in pixels |
| $1C || 2 || int16 || newYPixels || New Y position in pixels |
||
|- |
|- |
||
| $1E || 2 || int16 x4 || New X position |
| $1E || 2 || int16 x4 || newX || New X position |
||
|- |
|- |
||
| $20 || 2 || int16 x4 || New Y position |
| $20 || 2 || int16 x4 || newY || New Y position |
||
|- |
|- |
||
| $22 || 2 || int16 0-based || Health |
| $22 || 2 || int16 0-based || health || Health |
||
|- |
|- |
||
| $24 || 2 || uint16 || Current state (0 = targeting, 1 = mimicking) |
| $24 || 2 || uint16 || mimicking || Current state (0 = targeting, 1 = mimicking) |
||
|- |
|- |
||
| $26 || 2 || uint16 || Number of frames until state change |
| $26 || 2 || uint16 || framesUntilStateSwitch || Number of frames until state change |
||
|- |
|- |
||
| $28 || 2 || pointer16 || Pointer to spawn animation |
| $28 || 2 || pointer16 || spawnAnimation || Pointer to spawn animation |
||
|- |
|- |
||
| $2A || 2 || pointer16 || Pointer to walking animations table |
| $2A || 2 || pointer16 || walkingAnimations || Pointer to walking animations table |
||
|- |
|- |
||
| $2C || 2 || uint16 x2 || Which player is being cloned |
| $2C || 2 || uint16 x2 || clonedPlayer || Which player is being cloned |
||
|- |
|- |
||
| $2E || 2 || boolean || Dead |
| $2E || 2 || boolean || dead || Dead |
||
|- |
|- |
||
| $30 || 2 || sprite type || Type of weapon shot sprite collided with |
| $30 || 2 || sprite type || collidedSpriteType || Type of weapon shot sprite collided with |
||
|- class="breakrow" |
|- class="breakrow" |
||
| $7E || 2 || |
| $7E || 2 || int16 0-based || freezeTimer || Number of times hit with [[fire extinguisher]] |
||
|} |
|} |
||
== Psuedocode == |
|||
init() { |
|||
{{ROM name|$81:8000}}() |
|||
this.x = args.x * 4 |
|||
this.y = args.y * 4 |
|||
this.sprite.tileData = $90:9F0D |
|||
this.sprite.visible = true |
|||
this.framesUntilAnimUpdate = 7 |
|||
this.animationFrame = 0 |
|||
this.sprite.tileData.bank = 0x90 |
|||
this.framesUntilStateSwitch = 1 |
|||
{{ROM name|$80:CC3B}}(0x1A) |
|||
this.animationFrame = 0 |
|||
while (this.animationFrame < 11) { |
|||
this.sprite.tileData.lowBytes = this.spawnAnimation[this.animationFrame] |
|||
{{ROM name|$80:8353}}(10) |
|||
this.animationFrame += 1 |
|||
} |
|||
this.health = 0 |
|||
this.sprite.type = MONSTER |
|||
this.sprite.alternatePalette = 6 |
|||
{{ROM name|$80:8475}}(this.collisionHandler) |
|||
this.mimicking = false |
|||
this.collidedSpriteType = 0 |
|||
this.animationFrame = 0 |
|||
this.dead = false |
|||
this.freezeTimer = 0 |
|||
} |
|||
determineClonedPlayer() { |
|||
clonedCharacter = null |
|||
player = 1 |
|||
while (player >= 0) { |
|||
if (!{{RAM name|$7E:1E88}}[player]) { |
|||
clonedCharacter = {{RAM name|$7E:1E84}}[(player + 1) % 2] |
|||
break |
|||
} |
|||
player -= 1 |
|||
} |
|||
if (clonedCharacter = null) { |
|||
clonedCharacter = {{ROM name|$80:9D39}}() % 2 |
|||
} |
|||
this.walkingAnimations = this.walkingAnimationsPerCharacter[clonedCharacter] |
|||
this.spawnAnimation = this.spawnAnimationPerCharacter[clonedCharacter] |
|||
if ({{RAM name|$7E:1E88}}[0] && {{RAM name|$7E:1E84}}[0] == clonedCharacter) { |
|||
this.clonedPlayer = 0 |
|||
} else { |
|||
this.clonedPlayer = 1 |
|||
} |
|||
} |
|||
move(direction) { |
|||
this.newX = this.x + moveAmount[direction][0] |
|||
this.newXPixels = this.newX / 4 |
|||
this.newY = this.y + moveAmount[direction][1] |
|||
this.newYPixels = this.newY / 4 |
|||
if (!{{ROM name|$80:AE97}}(this.newXPixels, this.yPixels) && |
|||
!{{ROM name|$80:BF67}}(this.sprite, this.newXPixels, this.yPixels)) { |
|||
this.x = this.newX |
|||
this.xPixels = this.newXPixels |
|||
} |
|||
if (!{{ROM name|$80:AE97}}(this.xPixels, this.newYPixels) && |
|||
!{{ROM name|$80:BF67}}(this.sprite, this.xPixels, this.newYPixels)) { |
|||
this.y = this.newY |
|||
this.yPixels = this.newYPixels |
|||
} |
|||
this.sprite.x = this.xPixels |
|||
this.sprite.y = this.yPixels |
|||
if (this.direction < DOWN_LEFT) { |
|||
this.sprite.flipX = false |
|||
} else { |
|||
this.sprite.flipX = true |
|||
} |
|||
} |
|||
moveAmount = { { 0, 0 }, |
|||
{ 0, -3 }, |
|||
{ 3, -3 }, |
|||
{ 3, 0 }, |
|||
{ 3, 3 }, |
|||
{ 0, 3 }, |
|||
{ -3, 3 }, |
|||
{ -3, 0 }, |
|||
{ -3, -3 } } |
|||
updateAnimation() { |
|||
this.framesUntilAnimUpdate -= 1 |
|||
if (this.framesUntilAnimUpdate == 0) { |
|||
this.framesUntilAnimUpdate = 7 |
|||
this.animationFrame = (this.animationFrame + 1) % 4 |
|||
this.sprite.tileData.lowBytes = this.walkingAnimations[this.direction][this.animationFrame] |
|||
} |
|||
} |
|||
target() { |
|||
this.xPixels = this.x / 4 |
|||
this.yPixels = this.y / 4 |
|||
this.direction = {{ROM name|$80:B2A5}}(0xF0, this.xPixels, this.yPixels) |
|||
this.move(this.direction) |
|||
} |
|||
mimick() { |
|||
this.direction = {{RAM name|$7E:0072}}[this.clonedPlayer] |
|||
this.move(this.direction) |
|||
} |
|||
mainNormal() { |
|||
if (!{{RAM name|$7E:1E88}}[0] && !{{RAM name|$7E:1E88}}[1]) { |
|||
return |
|||
} |
|||
{{RAM name|$7E:00DE}} += 0x18 |
|||
this.determineClonedPlayer() |
|||
this.init() |
|||
while (true) { |
|||
{{ROM name|$80:8353}}(1) |
|||
if (this.dead) { |
|||
break |
|||
} |
|||
this.updateAnimation() |
|||
if (this.mimicking) { |
|||
this.mimick() |
|||
} else { |
|||
this.target() |
|||
if (this.direction == NONE) { |
|||
break |
|||
} |
|||
} |
|||
this.framesUntilStateSwitch -= 1 |
|||
if (this.framesUntilStateSwitch == 0) { |
|||
this.mimicking = !this.mimicking |
|||
this.framesUntilStateSwitch = {{ROM name|$80:9D39}}() |
|||
} |
|||
} |
|||
if (this.collidedSpriteType != 0) { |
|||
{{ROM name|$80:C7D9}}(this.collidedSpriteType & 0x8000, 20) |
|||
{{RAM name|$7E:1F76}} += 1 |
|||
{{ROM name|$81:83A3}}(this.deathAnimationNormal, 0xF5F5, 0x90) |
|||
} |
|||
{{ROM name|$80:BE41}}(this.sprite) |
|||
{{RAM name|$7E:00DE}} -= 0x18 |
|||
while ({{RAM name|$7E:00DE}} < 0) { } |
|||
} |
|||
deathAnimationNormal = { { 0xA01D, 5 }, { 0xA06E, 5 }, { 0xA0A7, 5 }, { 0xA0D8, 5 }, |
|||
{ 0xA0F9, 5 }, { 0xA11A, 5 } } |
|||
mainHard() { |
|||
if (!{{RAM name|$7E:1E88}}[0] && !{{RAM name|$7E:1E88}}[1]) { |
|||
return |
|||
} |
|||
{{RAM name|$7E:00DE}} += 0x18 |
|||
this.determineClonedPlayer() |
|||
this.init() |
|||
while (true) { |
|||
{{ROM name|$80:8353}}(1) |
|||
if (this.health < 0) { |
|||
break |
|||
} |
|||
this.updateAnimation() |
|||
this.target() |
|||
if (this.direction == NONE) { |
|||
break |
|||
} |
|||
this.target() |
|||
if (this.direction == NONE) { |
|||
break |
|||
} |
|||
} |
|||
if (this.collidedSpriteType != 0) { |
|||
{{ROM name|$80:C7D9}}(this.collidedSpriteType & 0x8000, 20) |
|||
{{RAM name|$7E:1F76}} += 1 |
|||
{{ROM name|$81:83A3}}(this.deathAnimationHard, 0xF5F5, 0x90) |
|||
} |
|||
{{ROM name|$80:BE41}}(this.sprite) |
|||
{{RAM name|$7E:00DE}} -= 0x18 |
|||
while ({{RAM name|$7E:00DE}} < 0) { } |
|||
} |
|||
deathAnimationHard = { { 0xA01D, 5 }, { 0xA06E, 5 }, { 0xA0A7, 5 }, { 0xA0D8, 5 }, |
|||
{ 0xA0F9, 5 }, { 0xA11A, 5 } } |
|||
walkingAnimationsPerCharacter = { walkingAnimationsZeke, walkingAnimationsJulie } |
|||
walkingAnimationsZeke = { { 0x90ED, 0x90ED, 0x90ED, 0x90ED }, |
|||
{ 0x9210, 0x9229, 0x9242, 0x925B }, |
|||
{ 0x9138, 0x9159, 0x9172, 0x9193 }, |
|||
{ 0x9138, 0x9159, 0x9172, 0x9193 }, |
|||
{ 0x9138, 0x9159, 0x9172, 0x9193 }, |
|||
{ 0x91AC, 0x91C5, 0x91DE, 0x91F7 }, |
|||
{ 0x9138, 0x9159, 0x9172, 0x9193 }, |
|||
{ 0x9138, 0x9159, 0x9172, 0x9193 }, |
|||
{ 0x9138, 0x9159, 0x9172, 0x9193 } } |
|||
walkingAnimationsJulie = { { 0x8285, 0x8285, 0x8285, 0x8285 }, |
|||
{ 0x83B8, 0x83D1, 0x83EA, 0x8403 }, |
|||
{ 0x82E0, 0x8301, 0x831A, 0x833B }, |
|||
{ 0x82E0, 0x8301, 0x831A, 0x833B }, |
|||
{ 0x82E0, 0x8301, 0x831A, 0x833B }, |
|||
{ 0x8354, 0x836D, 0x8386, 0x839F }, |
|||
{ 0x82E0, 0x8301, 0x831A, 0x833B }, |
|||
{ 0x82E0, 0x8301, 0x831A, 0x833B }, |
|||
{ 0x82E0, 0x8301, 0x831A, 0x833B } } |
|||
spawnAnimationPerCharacter = { spawnAnimationZeke, spawnAnimationJulie } |
|||
spawnAnimationZeke = { 0x9F0D, 0x9F16, 0x9F27, 0x9F48, 0x9F69, 0x9F92, 0x9FC3, 0x9FF4, |
|||
0x9627, 0x9640, 0x9659 } |
|||
spawnAnimationJulie = { 0x9F0D, 0x9F16, 0x9F27, 0x9F48, 0x9F69, 0x9F92, 0x9FC3, 0x9FF4, |
|||
0x87C7, 0x87E0, 0x87F9 } |
|||
collisionHandler(spriteType) { |
|||
if (spriteType < SQUIRT_GUN) { |
|||
return false |
|||
} |
|||
this.collidedSpriteType = spriteType |
|||
weaponType = spriteType & 0x7FFF |
|||
if (weaponType == MARTIAN_BUBBLE_GUN) { |
|||
return {{ROM name|$81:83C6}}() |
|||
} else if (weaponType == FIRE_EXTINGUISHER) { |
|||
return {{ROM name|$81:847E}}() |
|||
} else { |
|||
newHealth = this.health - {{ROM name|$81:8561}}[weaponType - SQUIRT_GUN] |
|||
if (newHealth < 0) { |
|||
this.dead = true |
|||
this.health = newHealth |
|||
this.freezeTimer = 0 |
|||
return true |
|||
} else if (newHealth != this.health { |
|||
this.health = newHealth |
|||
return {{ROM name|$81:8506}}() |
|||
} |
|||
return false |
|||
} |
|||
} |
|||
[[Category:Respawning monster]] |
[[Category:Respawning monster]] |