wwf-wrestlemania/COLLIS.ASM

965 lines
17 KiB
NASM
Raw Normal View History

2021-04-06 15:21:54 -07:00
**************************************************************
*
* Software: Jamie Rivett
* Initiated: 9/10/93
*
* COPYRIGHT (C) 1992 WILLIAMS ELECTRONICS GAMES, INC.
*
**************************************************************
.file "collis.asm"
.title "game collision code"
.width 132
.option b,d,l,t
.mnolist
.include "macros.h"
.include "mproc.equ" ;Mproc equates
.include "display.equ" ;Display proc equates
.include "gsp.equ" ;Gsp asm equates
.include "sys.equ"
.include "game.equ"
.include "plyr.equ"
.include "anim.equ"
.include "audit.equ"
.include "special.equ"
******************************************************************************
* EXTERNAL REFERENCES
.ref process_ptrs
.ref get_opp_plyrmode
.ref round_tickcount
.ref wrestler_hit,ck_live_teammates
.ref special_hit
.ref wrestler_hit_special
.ref plyr1_objlist
.ref plyr2_objlist
.ref neutral_objlist
******************************************************************************
* SYMBOLS DEFINED IN THIS FILE
.if DEBUG
BSSX safe_plyr,16
.endif
******************************************************************************
* EQUATES FOR THIS FILE
#*****************************************************************************
SUBR overlap_collision
;don't check this for zombies
move *a13(STATUS_FLAGS),a14
btst B_ZOMBIE,a14
jrnz #exit
movi process_ptrs,a9
movi NUM_WRES,a10
#collis_loop
.align
move *a9+,a11,L
jrz #inactive
cmp a11,a13
jreq #skip ;skip self
move *a11(PLYRMODE),a14 ;walk through dead
cmpi MODE_DEAD,a14
jreq #skip
move *a11(ANIMODE),a0
btst MODE_OVERLAP_BIT,a0 ;allow overlap?
jrnz #skip
;skip this. if you wanna be able to go through someone, set your
;MODE_OVERLAP bit. NOCOLLIS should only apply to attack collisions.
; move *a13(ANIMODE),a0
; move *a11(ANIMODE),a1
; or a1,a0
; btst MODE_NOCOLLIS_BIT,a0
; jrnz #skip
move *a11(ATTACH_PROC),a0,L ;skip this if attached
cmp a0,a13
jreq #skip
move *a13(PLYRMODE),a0 ;if player is on ground and
cmpi MODE_ONGROUND,a0 ;then he can't move
jreq #skip
cmpi MODE_DEAD,a0 ;check dead too
jreq #skip
move *a13(PLYRMODE),a0 ;if player is running (or bouncing)
cmpi MODE_RUNNING,a0 ;and opponent is on ground
jreq #running ;then run through him
cmpi MODE_BOUNCING,a0
jrne #not_running
#running
calla get_opp_plyrmode
cmpi MODE_ONGROUND,a0
jreq #skip
#not_running
move *a13(ANIMODE),a0
btst MODE_OVERLAP_BIT,a0 ;allow overlap?
jrnz #skip
move *a13(OBJ_COLLX2),a5
move *a11(OBJ_COLLX1),a1
sub a1,a5 ;Ax2 - Bx1
jrle #no_overlap ;a5 = ROX
move *a13(OBJ_COLLX1),a0
move *a11(OBJ_COLLX2),a6
sub a0,a6 ;Bx2 - Ax1
jrle #no_overlap ;a6 = LOX
move *a13(OBJ_COLLZ2),a7
move *a11(OBJ_COLLZ1),a1
sub a1,a7 ;Az2 - Bz1
jrle #no_overlap ;a7 = BOZ
move *a13(OBJ_COLLZ1),a0
move *a11(OBJ_COLLZ2),a8
sub a0,a8 ;Bz2 - Az1
jrle #no_overlap ;a8 = TOZ
move *a13(OBJ_COLLY2),a1
move *a11(OBJ_COLLY1),a0
sub a0,a1 ;Ay2 - By1
jrle #no_overlap
move *a13(OBJ_COLLY1),a1
move *a11(OBJ_COLLY2),a0
sub a1,a0 ;By2 - Ay1
jrle #no_overlap
move *a13(PLYRMODE),a0
cmpi MODE_RUNNING,a0
jreq #up_down
move a5,a0
cmp a6,a5 ;a5-a6 (ROX-LOX)
jrlt #rox_min
move a6,a0
#rox_min
move a7,a1
cmp a8,a7 ;a7-a8 (BOZ-TOZ)
jrlt #boz_min
move a8,a1
#boz_min
move *a11(PLYRMODE),a14 ;if opp is on ground then
cmpi MODE_ONGROUND,a14 ;slide off in Z
jrne #skp
srl 1,a0 ;DZ / 2
#skp
cmp a1,a0 ;a0-a1 (MOX-MOZ)
jrgt #up_down
;X glitch too big?
cmpi 3dh,a1
jrgt #up_down
;#left_right
cmp a6,a5 ;a5-a6 (ROX-LOX)
jrgt #right
;#left
move *a13(OBJ_XPOSINT),a0
sub a5,a0 ;XPOS-ROX
move a0,*a13(OBJ_XPOSINT)
jruc #ud2
#right
move *a13(OBJ_XPOSINT),a0
add a6,a0 ;XPOS+LOX
move a0,*a13(OBJ_XPOSINT)
#ud2
move *a13(MOVE_DIR),a0
jrz #exit
andi MOVE_UP|MOVE_DOWN,a0
jrnz #exit
movi 3,a0
cmp a8,a7 ;a7-a8 (BOZ-TOZ)
jrgt #d2
neg a0
#d2
move *a13(OBJ_ZPOSINT),a14
add a0,a14
move a14,*a13(OBJ_ZPOSINT)
rets
#up_down
cmp a8,a7 ;a7-a8 (BOZ-TOZ)
jrgt #down
;#up
move *a13(OBJ_ZPOSINT),a0
sub a7,a0 ;XPOS-BOZ
move a0,*a13(OBJ_ZPOSINT)
jruc #lr2
#down
move *a13(OBJ_ZPOSINT),a0
add a8,a0 ;XPOS-TOZ
move a0,*a13(OBJ_ZPOSINT)
#lr2
move *a13(MOVE_DIR),a0
jrz #exit
andi MOVE_LEFT|MOVE_RIGHT,a0
jrnz #exit
movi 3,a0
cmp a6,a5 ;a5-a6 (ROX-LOX)
jrgt #r2
neg a0
#r2
move *a13(OBJ_XPOSINT),a14
add a0,a14
move a14,*a13(OBJ_XPOSINT)
rets
#no_overlap
#skip
#inactive
dsj a10,#collis_loop
#exit
rets
#*****************************************************************************
SUBR set_collision_boxes
move *a13(CUR_FRAME),a4,L
;; move *a4(12*16),*a13(OBJ_BOXXOFF) ;x off
;; move *a4(13*16),*a13(OBJ_BOXYOFF) ;y off
;; move *a4(14*16),*a13(OBJ_BOXWIDTH) ;width
;; move *a4(15*16),*a13(OBJ_BOXHEIGHT) ;height
movi -30,a0
move a0,*a13(OBJ_BOXZOFF)
movi 60,a0
move a0,*a13(OBJ_BOXDEPTH)
move *a13(PLYRMODE),a0
cmpi MODE_ONGROUND,a0
;If running, have a smaller Z depth
jrnz #next
movi -15,a0
move a0,*a13(OBJ_BOXZOFF)
movi 30,a0
move a0,*a13(OBJ_BOXDEPTH)
jruc #norm
#next
cmpi MODE_RUNNING,a0
jrnz #norm
movi -5,a0
move a0,*a13(OBJ_BOXZOFF)
movi 10,a0
move a0,*a13(OBJ_BOXDEPTH)
#norm
;***********************************************************
;
;XJR - maybe add 100 or so to the initial Y-pos so
; that colly1 or y2 never become negative...
;
;***********************************************************
move *a13(OBJ_YPOSINT),a0
; move *a4(14*16),a1 ;BOX YOFF
move *a4(IANI3Y),a1 ;BOX YOFF
sub a1,a0
move a0,*a13(OBJ_COLLY2)
; move *a4(16*16),a1 ;BOX HEIGHT
move *a4(IANI3ID),a1 ;BOX HEIGHT
sub a1,a0
move a0,*a13(OBJ_COLLY1)
move *a13(OBJ_ZPOSINT),a0
move *a13(OBJ_BOXZOFF),a1
add a1,a0
move a0,*a13(OBJ_COLLZ1)
move *a13(OBJ_BOXDEPTH),a1
add a1,a0
move a0,*a13(OBJ_COLLZ2)
move *a13(OBJ_CONTROL),a0
btst B_FLIPH,a0
jrz #not_flipped
;#flipped
move *a13(OBJ_XPOSINT),a0
; move *a4(13*16),a1 ;BOX XOFF
move *a4(IANI3X),a1 ;BOX XOFF
sub a1,a0
move a0,*a13(OBJ_COLLX2)
; move *a4(15*16),a1 ;BOX WIDTH
move *a4(IANI3Z),a1 ;BOX WIDTH
sub a1,a0
move a0,*a13(OBJ_COLLX1)
rets
#not_flipped
move *a13(OBJ_XPOSINT),a0
; move *a4(13*16),a1 ;BOX XOFF
move *a4(IANI3X),a1 ;BOX XOFF
add a1,a0
move a0,*a13(OBJ_COLLX1)
; move *a4(15*16),a1 ;BOX WIDTH
move *a4(IANI3Z),a1 ;BOX WIDTH
add a1,a0
move a0,*a13(OBJ_COLLX2)
rets
#*****************************************************************************
.bss x1,16
.bss x2,16
.bss y1,16
.bss y2,16
.bss z1,16
.bss z2,16
SUBR check_collisions
callr object_collisions
PUSH a13
move @round_tickcount,a0
andi 1,a0
jrz #even
;odd
movi process_ptrs+32*NUM_WRES,a4
movi NUM_WRES,a5
#collis_loop1
move -*a4,a10,L
jrz #inactive1
move *a10(ANIMODE),a0
btst MODE_CHECKHIT_BIT,a0
jrz #inactive1
PUSH a4,a5
callr set_xyz
movi process_ptrs,a4
movi NUM_WRES,a5
#collis_loop2
move *a4+,a13,L
jrz #inactive2
cmp a10,a13
jreq #skip_self
PUSH a4,a5
callr check_collis
PULL a4,a5
move *a10(ANIMODE),a0
btst MODE_STATUS_BIT,a0 ;hit someone?
jrnz #done
#skip_self
#inactive2
dsj a5,#collis_loop2
PULL a4,a5
#inactive1
dsj a5,#collis_loop1
PULL a13
rets
#done
PULL a4,a5
PULL a13
rets
#even
#*
movi process_ptrs,a4
movi NUM_WRES,a5
#collis_loop1
move *a4+,a10,L
jrz #inactive1
move *a10(ANIMODE),a0
btst MODE_CHECKHIT_BIT,a0
jrz #inactive1
PUSH a4,a5
callr set_xyz
movi process_ptrs,a4
movi NUM_WRES,a5
#collis_loop2
move *a4+,a13,L
jrz #inactive2
cmp a10,a13
jreq #skip_self
PUSH a4,a5
callr check_collis
PULL a4,a5
move *a10(ANIMODE),a0
btst MODE_STATUS_BIT,a0 ;hit someone?
jrnz #done
#skip_self
#inactive2
dsj a5,#collis_loop2
PULL a4,a5
#inactive1
dsj a5,#collis_loop1
PULL a13
rets
#done
PULL a4,a5
PULL a13
rets
#*****************************************************************************
* a10 = * offensive process
* a13 = * defensive process
SUBRP check_collis
move *a13(ANIMODE),a0
btst MODE_NOCOLLIS_BIT,a0
jrnz #no_hit
;if you're immobilized, you can't hit anyone
move *a10(IMMOBILIZE_TIME),a0
jrnz #no_hit
move @x1,a0
move *a13(OBJ_COLLX2),a1
cmp a0,a1 ;Dx2 - Ox1
jrlt #no_hit ;if Dx2 < Ox1
move @x2,a0
move *a13(OBJ_COLLX1),a1
cmp a0,a1 ;Dx1 - Ox2
jrgt #no_hit ;if Dx1 > Ox2
move @y1,a0
move *a13(OBJ_COLLY2),a1
cmp a0,a1 ;Dy2 - Oy1
jrlt #no_hit ;if Dy2 < Oy1
move @y2,a0
move *a13(OBJ_COLLY1),a1
cmp a0,a1 ;Dy1 - Oy2
jrgt #no_hit ;if Dy1 > Oy2
move @z1,a0
move *a13(OBJ_COLLZ2),a1
cmp a0,a1 ;Dz2 - Oz1
jrlt #no_hit ;Dz2 < Oz1
move @z2,a0
move *a13(OBJ_COLLZ1),a1
cmp a0,a1 ;Dz1 - Oz2
jrgt #no_hit ;Dz1 > Oz2
;we've found a hit. ignore if attacker is in SMART_ATTACK mode and
; victim doesn't match his target. We check this AFTER a hit is
; registered because it's an unlikely case and checking it beforehand
; wastes time.
move *a10(STATUS_FLAGS),a0
btst B_SMART_ATTACK,a0
jrz #not_smart
move *a10(SMART_TARGET),a0,L
cmp a0,a13
jrne #no_hit
#not_smart
;if attacker is in combo mode, only allow hits on his WHOIHIT.
move *a10(COMBO_COUNT),a14
jrz #not_combo
move *a10(WHOIHIT),a14,L
cmp a13,a14
jrne #no_hit
#not_combo
;check for a dead victim with live teammates.
move *a13(PLYRMODE),a0
cmpi MODE_DEAD,a0
jrne #not_dead
move a13,a0
calla ck_live_teammates
jrc #no_hit
;check for a dead victim and an AMODE_PUPPET attack.
move *a10(ATTACK_MODE),a14
cmpi AMODE_PUPPET,a14
jreq #no_hit
cmpi AMODE_PUPPET2,a14
jreq #no_hit
#not_dead
;zombies can never be hit
move *a13(STATUS_FLAGS),a14
btst B_ZOMBIE,a14
jrnz #no_hit
;pinned wrestlers can only be hit by wrestlers who've done pins.
move *a10(STATUS_FLAGS),a14
btst B_DID_PIN,a14
jrnz #not_pinned
move *a13(STATUS_FLAGS),a14
btst B_PINNED,a14
jrnz #no_hit
#not_pinned
;make sure INRING values match
move *a10(INRING),a0
move *a13(INRING),a14
cmp a0,a14
jrne #no_hit
;if victim is in MODE_INAIR or MODE_INAIR2, don't let pushes hit.
move *a10(ATTACK_MODE),a14
cmpi AMODE_PUSH,a14
jrne #no_pushfly
move *a13(PLYRMODE),a14
cmpi MODE_INAIR,a14
jreq #no_hit
cmpi MODE_INAIR2,a14
jreq #no_hit
#no_pushfly
;if the victim is doing a push, his PUSH bit will be set in status
; flags. If it is, only flying attacks can hit him.
move *a13(STATUS_FLAGS),a14,L
btst B_PUSH,a14
jrz #not_push
move *a10(ATTACK_MODE),a14
cmpi AMODE_FLYKICK,a14
jreq #not_push
cmpi AMODE_BSTOMP,a14
jreq #not_push
cmpi AMODE_BLBOWDROP,a14
jreq #not_push
jruc #no_hit
#not_push
;if attacker is in MODE_WAITHITOPP, clear said bit and zero ANICNTs.
move *a10(ANIMODE),a14
btst MODE_WAITHITOPP_BIT,a14
jrz #skip_whopp
andni MODE_WAITHITOPP,a14
move a14,*a10(ANIMODE)
clr a14
move a14,*a10(ANICNT)
move a14,*a10(ANICNT2)
#skip_whopp
.if DEBUG
;if safe_plyr is set, disregard attacks on players
move @safe_plyr,a14
jrz #skip_safeplyr
move *a13(PLYR_TYPE),a14
cmpi PTYPE_PLAYER,a14
jreq #no_hit
#skip_safeplyr
.endif
clr a14 ;false
move *a13(PLYRMODE),a0
cmpi MODE_BLOCK,a0
jrne #noblock
inc a14 ;true
#noblock
move a14,*a10(HITBLOCKER)
movi MOVE_RIGHT,a0
move *a10(OBJ_XPOSINT),a1
move *a13(OBJ_XPOSINT),a2
cmp a2,a1
jrgt #hit_from_right
movi MOVE_LEFT,a0
#hit_from_right
movi MOVE_DOWN,a14
move *a10(OBJ_ZPOS),a1,L
move *a13(OBJ_ZPOS),a2,L
cmp a2,a1
jrgt #hit_from_below
movi MOVE_UP,a14
#hit_from_below
or a14,a0
move a0,*a13(PLYR_HIT_SIDE)
move a0,*a10(PLYR_HIT_SIDE)
move *a10(ANIMODE),a0
ori MODE_STATUS,a0 ;this flag set whenever
move a0,*a10(ANIMODE) ;a successful hit
calla wrestler_hit
#no_hit
rets
#*****************************************************************************
* a10 = *process
* sets x1,x2,y1,y2,z1 and z2
SUBRP set_xyz
move *a10(OBJ_YPOSINT),a0
move *a10(OBJ_ATTYOFF),a1
add a1,a0
move a0,@y1
move *a10(OBJ_ATTHEIGHT),a1
add a1,a0
move a0,@y2
move *a10(OBJ_ZPOSINT),a0
move *a10(OBJ_ATTZOFF),a1
add a1,a0
move a0,@z1
move *a10(OBJ_ATTDEPTH),a1
add a1,a0
move a0,@z2
; move *a10(FACING_DIR),a14
; btst PLAYER_RIGHT_BIT,a14
; jrnz #facing_right
move *a10(OBJ_CONTROL),a14
btst B_FLIPH,a14
jrz #facing_right
;facing_left
move *a10(OBJ_XPOSINT),a0
move *a10(OBJ_ATTXOFF),a1
sub a1,a0
move a0,@x2
move *a10(OBJ_ATTWIDTH),a1
sub a1,a0
move a0,@x1
rets
#facing_right
move *a10(OBJ_XPOSINT),a0
move *a10(OBJ_ATTXOFF),a1
add a1,a0
move a0,@x1
move *a10(OBJ_ATTWIDTH),a1
add a1,a0
move a0,@x2
rets
#*****************************************************************************
*
* a10 = * wrestler process to turn collisions off
SUBR wres_collis_off
move *a10(ANIMODE),a0
andni MODE_CHECKHIT,a0
move a0,*a10(ANIMODE)
rets
#*****************************************************************************
SUBR object_collisions
;FIX!!! This can point to a non existent proc
movi plyr1_objlist,a0
callr set_spobj_boxes
movi plyr2_objlist,a0
callr set_spobj_boxes
movi neutral_objlist,a0
callr set_spobj_boxes
movi plyr1_objlist,a6
movi plyr2_objlist,a7
callr objlist2objlist_collis
movi plyr1_objlist,a10
callr objlist2player_collis
movi plyr2_objlist,a10
callr objlist2player_collis
movi neutral_objlist,a10
callr objlist2player_collis
rets
#*****************************************************************************
;a10 = objlist1
objlist2player_collis
PUSH a13
move *a10,a10,L
jrz #done
#lp1
move *a10(SP_COLLX1),a0
move *a10(SP_COLLX2),a1
move *a10(SP_COLLY1),a2
move *a10(SP_COLLY2),a3
move *a10(SP_COLLZ1),a4
move *a10(SP_COLLZ2),a5
movi process_ptrs,a7
movi NUM_WRES,a6
#collis_loop
move *a7+,a13,L
jrz #inactive
move *a13(ANIMODE),a14
btst MODE_NOCOLLIS_BIT,a14
jrnz #no_hit
;check if projectile should hit this guy...(same side)
move *a13(OBJ_COLLX2),a14
cmp a0,a14 ;Dx2 - Ox1
jrlt #no_hit ;if Dx2 < Ox1
move *a13(OBJ_COLLX1),a14
cmp a1,a14 ;Dx1 - Ox2
jrgt #no_hit ;if Dx1 > Ox2
move *a13(OBJ_COLLY2),a14
cmp a2,a14 ;Dy2 - Oy1
jrlt #no_hit ;if Dy2 < Oy1
move *a13(OBJ_COLLY1),a14
cmp a3,a14 ;Dy1 - Oy2
jrgt #no_hit ;if Dy1 > Oy2
move *a13(OBJ_COLLZ2),a14
cmp a4,a14 ;Dz2 - Oz1
jrlt #no_hit ;Dz2 < Oz1
move *a13(OBJ_COLLZ1),a14
cmp a5,a14 ;Dz1 - Oz2
jrgt #no_hit ;Dz1 > Oz2
;hit
calla wrestler_hit_special
jruc #done
#no_hit
#inactive
dsj a6,#collis_loop
move *a10(SP_NEXT),a10,L
jrnz #lp1
#done
PULL a13
rets
#*****************************************************************************
;a6 = objlist1
;a7 = objlist2
objlist2objlist_collis
move *a6,a6,L
jrz #done
#lp1
move a7,a8
move *a8,a8,L
jrz #done
move *a6(SP_COLLX1),a0
move *a6(SP_COLLX2),a1
move *a6(SP_COLLY1),a2
move *a6(SP_COLLY2),a3
move *a6(SP_COLLZ1),a4
move *a6(SP_COLLZ2),a5
#lp2
move *a8(SP_COLLX2),a14
cmp a0,a14 ;Dx2 - Ox1
jrlt #no_hit ;if Dx2 < Ox1
move *a8(SP_COLLX1),a14
cmp a1,a14 ;Dx1 - Ox2
jrgt #no_hit ;if Dx1 > Ox2
move *a8(SP_COLLY2),a14
cmp a2,a14 ;Dy2 - Oy1
jrlt #no_hit ;if Dy2 < Oy1
move *a8(SP_COLLY1),a14
cmp a3,a14 ;Dy1 - Oy2
jrgt #no_hit ;if Dy1 > Oy2
move *a8(SP_COLLZ2),a14
cmp a4,a14 ;Dz2 - Oz1
jrlt #no_hit ;Dz2 < Oz1
move *a8(SP_COLLZ1),a14
cmp a5,a14 ;Dz1 - Oz2
jrgt #no_hit ;Dz1 > Oz2
;hit
calla special_hit
jruc #done
#no_hit
move *a8(SP_NEXT),a8,L
jrnz #lp2
move *a6(SP_NEXT),a6,L
jrnz #lp1
#done
rets
#*****************************************************************************
set_spobj_boxes
move *a0,a0,L
jrz #done
#lp
move *a0(SP_OBJ_YPOSINT),a1
move *a0(SP_YOFF),a14
add a14,a1
move a1,*a0(SP_COLLY1)
move *a0(SP_HEIGHT),a14
add a14,a1
move a1,*a0(SP_COLLY2)
move *a0(SP_OBJ_ZPOSINT),a1
move *a0(SP_ZOFF),a14
add a14,a1
move a1,*a0(SP_COLLZ1)
move *a0(SP_DEPTH),a14
add a14,a1
move a1,*a0(SP_COLLZ2)
move *a0(SP_OBJCONTROL),a14
btst B_FLIPH,a14
jrz #not_flipped
;#flipped
move *a0(SP_OBJ_XPOSINT),a1
move *a0(SP_XOFF),a14
sub a14,a1
move a1,*a0(SP_COLLX2)
move *a0(SP_WIDTH),a14
sub a14,a1
move a1,*a0(SP_COLLX1)
jruc #cnt
#not_flipped
move *a0(SP_OBJ_XPOSINT),a1
move *a0(SP_XOFF),a14
add a14,a1
move a1,*a0(SP_COLLX1)
move *a0(SP_WIDTH),a14
add a14,a1
move a1,*a0(SP_COLLX2)
#cnt
move *a0(SP_NEXT),a0,L
jrnz #lp
#done
rets
******************************************************************************
.end