************************************************************** * * 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