mirror of https://github.com/Blzut3/Wolf3D-Mac.git synced 2024-06-17 11:29:36 +00:00
 ```/* enmove.c*/ ``` ```#include "wolfdef.h" ``` ``` ``` ```dirtype opposite[9] = ``` ``` {west,southwest,south,southeast,east,northeast,north,northwest,nodir}; ``` ``` ``` ```dirtype diagonal[9][9] = { ``` ```/* east */ {nodir,nodir,northeast,nodir,nodir,nodir,southeast,nodir,nodir}, ``` ``` {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir}, ``` ```/* north */ {northeast,nodir,nodir,nodir,northwest,nodir,nodir,nodir,nodir}, ``` ``` {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir}, ``` ```/* west */ {nodir,nodir,northwest,nodir,nodir,nodir,southwest,nodir,nodir}, ``` ``` {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir}, ``` ```/* south */ {southeast,nodir,nodir,nodir,southwest,nodir,nodir,nodir,nodir}, ``` ``` {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir}, ``` ``` {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir} ``` ```}; ``` ``` ``` ```/********************************** ``` ``` ``` ``` Changes actor to a new state, setting ticcount to the max for that state ``` ``` ``` ```**********************************/ ``` ``` ``` ```void NewState(actor_t *ActorPtr,stateindex_t state) ``` ```{ ``` ``` state_t *StatePtr; ``` ``` StatePtr = &states[state]; /* Get the state record pointer */ ``` ``` ActorPtr->state = state; /* Set the actor's state */ ``` ``` ActorPtr->ticcount = StatePtr->tictime; /* Set the initial tick value */ ``` ``` ActorPtr->pic = StatePtr->shapenum; /* Set the current shape number */ ``` ```} ``` ``` ``` ```/********************************** ``` ``` ``` ``` Attempts to move actor in its current (ActorPtr->dir) direction. ``` ``` ``` ``` If blocked by either a wall or an actor returns FALSE ``` ``` ``` ``` If move is either clear or blocked only by a door, returns TRUE and sets ``` ``` ``` ``` ActorPtr->tilex = new destination ``` ``` ActorPtr->tiley ``` ``` ActorPtr->areanumber = the floor tile number (0-(MAXAREAS-1)) of destination ``` ``` ActorPtr->distance = TILEGLOBAL, or doornumber if a door is blocking the way ``` ``` ``` ``` If a door is in the way, an OpenDoor call is made to start it opening. ``` ``` The actor code should wait until ``` ``` doorobjlist[ActorPtr->distance].action = dr_open, meaning the door has been ``` ``` fully opened ``` ``` ``` ```**********************************/ ``` ``` ``` ```/********************************** ``` ``` ``` ``` Check if I can move in a diagonal direction ``` ``` ``` ```**********************************/ ``` ``` ``` ```Boolean CheckDiag(Word x,Word y) ``` ```{ ``` ``` /* anything blocking stops diagonal move*/ ``` ``` if (tilemap[y][x]&(TI_BLOCKMOVE|TI_ACTOR)) { ``` ``` return FALSE; /* It's blocked */ ``` ``` } ``` ``` return TRUE; /* It's open! */ ``` ```} ``` ``` ``` ```/********************************** ``` ``` ``` ``` Check if I can move in a sideways direction ``` ``` also do the code for an actor to open a door ``` ``` return 0 if blocked, 1 if open, 2 if I need to open a door ``` ``` ``` ```**********************************/ ``` ``` ``` ```Word CheckSide(Word x,Word y,actor_t *ActorPtr) ``` ```{ ``` ``` Word temp; ``` ``` ``` ``` temp=tilemap[y][x]; /* Get the tile */ ``` ``` ``` ``` if (temp & TI_DOOR) { /* Door? */ ``` ``` if (!(temp&TI_BLOCKMOVE)) { /* Not blocked? */ ``` ``` return 1; /* door is open*/ ``` ``` } ``` ``` if (ActorPtr->class == CL_DOG) { ``` ``` return 0; /* dogs can't open doors */ ``` ``` } ``` ``` return 2; /* I have to open the door */ ``` ``` } ``` ``` if (temp&(TI_BLOCKMOVE|TI_ACTOR)) { /* Normally blocked? */ ``` ``` return 0; /* Can't go this way */ ``` ``` } ``` ``` return 1; /* I can go! */ ``` ```} ``` ``` ``` ```/********************************** ``` ``` ``` ``` Try to move the actor around ``` ``` ``` ```**********************************/ ``` ``` ``` ```Boolean TryWalk (actor_t *ActorPtr) ``` ```{ ``` ``` Word x,y; ``` ``` Word Temp; ``` ``` Word *TileMapPtr; ``` ``` Word tile; ``` ``` ``` ``` x = ActorPtr->goalx; /* Where is my goal x,y? */ ``` ``` y = ActorPtr->goaly; ``` ``` ``` ``` switch (ActorPtr->dir) { /* Go in my direction */ ``` ``` case north: /* Go n,s,e,w */ ``` ``` --y; ``` ``` goto DoSide; ``` ``` ``` ``` case east: ``` ``` ++x; ``` ``` goto DoSide; ``` ``` ``` ``` case south: ``` ``` ++y; ``` ``` goto DoSide; ``` ``` ``` ``` case west: ``` ``` --x; ``` ```DoSide: ``` ``` Temp = CheckSide(x,y,ActorPtr); /* See if I can move this way */ ``` ``` if (!Temp) { /* Not this way? */ ``` ``` return FALSE; /* Exit */ ``` ``` } ``` ``` if (Temp==2) { /* Door? */ ``` ``` OpenDoor(&doors[tilemap[y][x]&TI_NUMMASK]); /* Open the door */ ``` ``` ActorPtr->flags |= (FL_WAITDOOR|FL_NOTMOVING); /* Force the actor to pause */ ``` ``` return TRUE; /* I'm ok! */ ``` ``` } ``` ``` break; /* Continue */ ``` ``` ``` ``` case northeast: ``` ``` if (!CheckDiag(x+1,y)) { ``` ``` return FALSE; ``` ``` } ``` ``` y--; ``` ``` goto FixEast; ``` ``` ``` ``` case southeast: ``` ``` if (!CheckDiag(x+1,y)) { ``` ``` return FALSE; ``` ``` } ``` ``` y++; ``` ```FixEast: ``` ``` if (!CheckDiag(x,y)) { ``` ``` return FALSE; ``` ``` } ``` ``` x++; ``` ``` if (!CheckDiag(x,y)) { ``` ``` return FALSE; ``` ``` } ``` ``` break; ``` ``` ``` ``` case southwest: ``` ``` if (!CheckDiag(x-1,y)) { ``` ``` return FALSE; ``` ``` } ``` ``` y++; ``` ``` goto FixWest; ``` ``` ``` ``` case northwest: ``` ``` if (!CheckDiag(x-1,y)) { ``` ``` return FALSE; ``` ``` } ``` ``` y--; ``` ```FixWest: ``` ``` if (!CheckDiag(x,y)) { ``` ``` return FALSE; ``` ``` } ``` ``` x--; ``` ``` if (!CheckDiag(x,y)) { ``` ``` return FALSE; ``` ``` } ``` ``` } ``` ``` ``` ```/* invalidate the move if moving onto the player */ ``` ``` ``` ``` if (areabyplayer[MapPtr->areasoundnum[ActorPtr->areanumber]]) { ``` ``` if (w_abs(((x<goaly][ActorPtr->goalx] &= ~TI_ACTOR; ``` ``` ``` ```/* place new actor marker*/ ``` ``` ``` ``` TileMapPtr = &tilemap[y][x]; /* Get pointer to cell */ ``` ``` tile = TileMapPtr[0]; /* Get the cell */ ``` ``` TileMapPtr[0] = tile | TI_ACTOR; /* Mark with an actor */ ``` ``` Temp = ActorPtr - &actors[0]; ``` ``` MapPtr->tilemap[y][x] = Temp; /* Save the current actor # */ ``` ``` ActorPtr->goalx = x; ``` ``` ActorPtr->goaly = y; ``` ``` ``` ``` if (!(tile&TI_DOOR) ) { /* doorways are not areas*/ ``` ``` ActorPtr->areanumber = tile&TI_NUMMASK; ``` ``` } ``` ``` ActorPtr->distance = TILEGLOBAL; /* Move across 1 whole tile */ ``` ``` ActorPtr->flags &= ~(FL_WAITDOOR|FL_NOTMOVING); /* I'm not waiting and I'm moving */ ``` ``` ``` ``` return TRUE; /* It's ok! */ ``` ```} ``` ``` ``` ```/********************************** ``` ``` ``` ``` Attempts to choose and initiate a movement for actor that sends it towards ``` ``` the player while dodging ``` ``` ``` ```**********************************/ ``` ``` ``` ```void SelectDodgeDir(actor_t *ActorPtr) ``` ```{ ``` ``` int deltax,deltay; ``` ``` Word i; ``` ``` Word absdx,absdy; ``` ``` dirtype dirtry[5]; ``` ``` dirtype turnaround,tdir; ``` ``` ``` ``` turnaround=opposite[ActorPtr->dir]; ``` ``` ``` ``` deltax = actors[0].x - ActorPtr->x; ``` ``` deltay = actors[0].y - ActorPtr->y; ``` ``` ``` ```/* arange 5 direction choices in order of preference*/ ``` ```/* the four cardinal directions plus the diagonal straight towards*/ ``` ```/* the player*/ ``` ``` ``` ``` if (deltax>0) { ``` ``` dirtry[1]= east; ``` ``` dirtry[3]= west; ``` ``` } else { ``` ``` dirtry[1]= west; ``` ``` dirtry[3]= east; ``` ``` } ``` ``` ``` ``` if (deltay>0) { ``` ``` dirtry[2]= south; ``` ``` dirtry[4]= north; ``` ``` } else { ``` ``` dirtry[2]= north; ``` ``` dirtry[4]= south; ``` ``` } ``` ``` ``` ```/* randomize a bit for dodging*/ ``` ``` ``` ``` absdx = w_abs(deltax); ``` ``` absdy = w_abs(deltay); ``` ``` ``` ``` if (absdx > absdy) { ``` ``` tdir = dirtry[1]; ``` ``` dirtry[1] = dirtry[2]; ``` ``` dirtry[2] = tdir; ``` ``` tdir = dirtry[3]; ``` ``` dirtry[3] = dirtry[4]; ``` ``` dirtry[4] = tdir; ``` ``` } ``` ``` ``` ``` if (w_rnd() & 1) { ``` ``` tdir = dirtry[1]; ``` ``` dirtry[1] = dirtry[2]; ``` ``` dirtry[2] = tdir; ``` ``` tdir = dirtry[3]; ``` ``` dirtry[3] = dirtry[4]; ``` ``` dirtry[4] = tdir; ``` ``` } ``` ``` ``` ``` dirtry[0] = diagonal[dirtry[1]][dirtry[2]]; ``` ``` ``` ```/* try the directions until one works*/ ``` ``` ``` ``` i = 0; ``` ``` do { ``` ``` tdir = dirtry[i]; ``` ``` if (tdir != nodir && tdir != turnaround) { ``` ``` ActorPtr->dir = tdir; ``` ``` if (TryWalk(ActorPtr)) { /* Can I go this way? */ ``` ``` return; /* Yep! */ ``` ``` } ``` ``` } ``` ``` } while(++i<5); /* All tries done? */ ``` ``` ``` ```/* turn around only as a last resort*/ ``` ``` ``` ``` if (turnaround != nodir) { ``` ``` ActorPtr->dir = turnaround; ``` ``` if (TryWalk(ActorPtr)) { ``` ``` return; ``` ``` } ``` ``` } ``` ``` ActorPtr->dir = nodir; /* Stop the motion */ ``` ``` ActorPtr->flags |= FL_NOTMOVING; /* Kill the logic! */ ``` ```} ``` ``` ``` ```/********************************** ``` ``` ``` ``` Attempts to choose and initiate a movement for actor that sends it towards ``` ``` the player but doesn't try to dodge ``` ``` ``` ```**********************************/ ``` ``` ``` ```void SelectChaseDir(actor_t *ActorPtr) ``` ```{ ``` ``` int deltax,deltay; ``` ``` dirtype d[3]; ``` ``` dirtype tdir, olddir, turnaround; ``` ``` ``` ``` olddir = (dirtype) ActorPtr->dir; /* Save the current direction */ ``` ``` turnaround=opposite[olddir]; /* What's the opposite direction */ ``` ``` ``` ``` deltax = actors[0].x - ActorPtr->x; /* Which way to travel? */ ``` ``` deltay = actors[0].y - ActorPtr->y; ``` ``` ``` ``` if (deltax>0) { ``` ``` d[1]= east; ``` ``` } else if (!deltax) { ``` ``` d[1]= nodir; ``` ``` } else { ``` ``` d[1]= west; ``` ``` } ``` ``` if (deltay>0) { ``` ``` d[2]=south; ``` ``` } else if (!deltay) { ``` ``` d[2]=nodir; ``` ``` } else { ``` ``` d[2]=north; ``` ``` } ``` ``` ``` ``` if (w_abs(deltay)>w_abs(deltax)) { /* Swap if Y is greater */ ``` ``` tdir=d[1]; ``` ``` d[1]=d[2]; ``` ``` d[2]=tdir; ``` ``` } ``` ``` ``` ``` if (d[1]==turnaround) { /* Try not to turn around */ ``` ``` d[1]=nodir; ``` ``` } ``` ``` if (d[2]==turnaround) { /* Try not to turn around */ ``` ``` d[2]=nodir; ``` ``` } ``` ``` ``` ``` if (d[1]!=nodir) { /* East/West movement? */ ``` ``` ActorPtr->dir = d[1]; /* Try to move */ ``` ``` if (TryWalk(ActorPtr)) { ``` ``` return; /*either moved forward or attacked*/ ``` ``` } ``` ``` } ``` ``` ``` ``` if (d[2]!=nodir) { /* North/South movement? */ ``` ``` ActorPtr->dir =d[2]; ``` ``` if (TryWalk(ActorPtr)) { ``` ``` return; ``` ``` } ``` ``` } ``` ``` ``` ```/* there is no direct path to the player, so pick another direction */ ``` ``` ``` ``` if (olddir!=nodir) { ``` ``` ActorPtr->dir =olddir; /* Continue in the old direction */ ``` ``` if (TryWalk(ActorPtr)) { ``` ``` return; ``` ``` } ``` ``` } ``` ``` ``` ``` if (w_rnd()&1) { /*randomly determine direction of search*/ ``` ``` tdir = north; ``` ``` do { ``` ``` if (tdir!=turnaround) { ``` ``` ActorPtr->dir =tdir; ``` ``` if (TryWalk(ActorPtr)) { ``` ``` return; ``` ``` } ``` ``` } ``` ``` } while(++tdir<(west+1)); ``` ``` } else { ``` ``` tdir = west; ``` ``` do { ``` ``` if (tdir!=turnaround) { ``` ``` ActorPtr->dir =tdir; ``` ``` if ( TryWalk(ActorPtr)) { ``` ``` return; ``` ``` } ``` ``` } ``` ``` } while(--tdir>=north); ``` ``` } ``` ``` ``` ``` if (turnaround != nodir) { /* Alright, try backwards now */ ``` ``` ActorPtr->dir =turnaround; ``` ``` if ( TryWalk(ActorPtr) ) { ``` ``` return; ``` ``` } ``` ``` } ``` ``` ActorPtr->dir = nodir; /* Can't move, I give up */ ``` ``` ActorPtr->flags |= FL_NOTMOVING; ``` ```} ``` ``` ``` ```/********************************** ``` ``` ``` ``` Moves actor global units in actor->dir direction ``` ``` Actors are not allowed to move inside the player ``` ``` Does NOT check to see if the move is tile map valid ``` ``` ``` ```**********************************/ ``` ``` ``` ```void MoveActor(actor_t *ActorPtr,Word move) ``` ```{ ``` ``` Word tryx,tryy; ``` ``` ``` ``` tryx = ActorPtr->x; /* Get the x and y */ ``` ``` tryy = ActorPtr->y; ``` ``` ``` ``` switch (ActorPtr->dir) {; ``` ``` case northeast: /* Move to the new x,y */ ``` ``` tryx += move; ``` ``` case north: ``` ``` tryy -= move; ``` ``` break; ``` ``` ``` ``` case southeast: ``` ``` tryy += move; ``` ``` case east: ``` ``` tryx += move; ``` ``` break; ``` ``` ``` ``` case southwest: ``` ``` tryx -= move; ``` ``` case south: ``` ``` tryy += move; ``` ``` break; ``` ``` ``` ``` case northwest: ``` ``` tryy -= move; ``` ``` case west: ``` ``` tryx -= move; ``` ``` } ``` ``` ``` ```/* check to make sure it's not moving on top of player*/ ``` ``` ``` ``` if (areabyplayer[MapPtr->areasoundnum[ActorPtr->areanumber]]) { ``` ``` if (w_abs(tryx - actors[0].x)distance-= move; /* Remove the distance */ ``` ``` ActorPtr->x = tryx; /* Save the new x,y */ ``` ``` ActorPtr->y = tryy; ``` ```} ```