This repository has been archived by the owner on Mar 23, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 12
/
Doors.c
319 lines (243 loc) · 8.28 KB
/
Doors.c
1
#include "Wolfdef.h"#include <string.h>/********************************** Rules for door operationdoor->position holds the amount the door is open, ranging from 0 to TILEGLOBAL-1The number of doors is limited to 64 because various fields are only 6 bitsOpen doors conect two areas, so sounds will travel between them and sight will be checked when the player is in a connected area.areaconnect has a list of connected area #'s, used to create the table areabyplayerEvery time a door opens or closes the areabyplayer matrix gets recalculated. An area is True if it connects with the player's current spor.**********************************//********************************** Insert a connection between two rooms Note: I can have MORE than one connection between rooms so it is VALID to have duplicate entries (1,6) & (1,6) Each call to AddConnection must be balanced with a call to RemoveConnection **********************************/void AddConnection(Word Area1,Word Area2){ connect_t *DestPtr; DestPtr = &areaconnect[ConnectCount]; /* Make pointer to the last record */ DestPtr->Area1 = Area1; /* Init the struct */ DestPtr->Area2 = Area2; ++ConnectCount; /* Add 1 to the valid list */}/********************************** Remove a connection between two rooms Note: I can have MORE than one connection between rooms so it is VALID to have duplicate entries (1,6) & (1,6) **********************************/void RemoveConnection(Word Area1,Word Area2){ Word i; connect_t *DestPtr; DestPtr = &areaconnect[0]; /* Init the scan pointer */ i = ConnectCount; /* Init the count */ if (!i) { return; } do { if (DestPtr->Area1 == Area1 && /* Match? */ DestPtr->Area2 == Area2) { --ConnectCount; /* Remove the count */ DestPtr[0] = areaconnect[ConnectCount]; /* Copy last to current */ break; /* I'm done! */ } ++DestPtr; /* Next entry to scan */ } while (--i); /* Should NEVER fall out! */}/********************************** Recursive routine to properly set the areabyplayer array by using the contents of the areaconnect array. Scans outward from playerarea, marking all connected areas. **********************************/void RecursiveConnect(Word areanumber){ Word i; Word j; connect_t *AreaPtr; areabyplayer[areanumber] = TRUE; /* Mark this spot (Prevent overflow) */ i = ConnectCount; /* Init index */ if (i) { /* No doors available? */ AreaPtr = &areaconnect[0]; /* Get a local pointer */ do { if (AreaPtr->Area1 == areanumber) { /* Am I in this pair? */ j = AreaPtr->Area2; /* Follow this path */ goto TryIt; } if (AreaPtr->Area2 == areanumber) { /* The other side? */ j = AreaPtr->Area1; /* Follow this side */TryIt: if (!areabyplayer[j]) { /* Already been here? */ RecursiveConnect(j); /* Link it in... */ } } ++AreaPtr; /* Next entry */ } while (--i); /* All done? */ }}/********************************** Properly set the areabyplayer record **********************************/void ConnectAreas(void){ memset(areabyplayer,0,sizeof(areabyplayer)); /* Zap the memory */ RecursiveConnect(MapPtr->areasoundnum[actors[0].areanumber]); /* Start here */}/********************************** Start a door opening **********************************/void OpenDoor(door_t *door){ if (door->action == DR_OPEN) { /* Already open? */ door->ticcount = 0; /* Reset open time (Keep open) */ } else { door->action = DR_OPENING; /* start it opening*/ } /* The door will be made passable when it is totally open */}/********************************** Start a door closing **********************************/void CloseDoor(door_t *door){ Word tile,tilex,tiley; Word *TilePtr; int delta;/* don't close on anything solid */ tilex = door->tilex; /* Get the current tile */ tiley = door->tiley; TilePtr = &tilemap[tiley][tilex]; /* Get pointer to tile map */ if (door->action != DR_OPENING) { /* In the middle of opening? */ /* don't close on an actor or bonus item */ tile = TilePtr[0]; /* What's the tile? */ if (tile & TI_BODY) { door->action = DR_WEDGEDOPEN; /* bodies never go away */ return; } if (tile & (TI_ACTOR | TI_GETABLE) ) { /* Removable? */ door->ticcount = 60; /* wait a while before trying to close again */ return; } /* Don't close on the player */ delta = actors[0].x - ((tilex<<8)|0x80); if (w_abs(delta) <= (0x82+PLAYERSIZE)) { delta = actors[0].y - ((tiley<<8)|0x80); if (w_abs(delta) <= (0x82+PLAYERSIZE)) { return; /* It's touching the player! */ } } } door->action = DR_CLOSING; /* Close the door */ TilePtr[0] |= (TI_BLOCKMOVE|TI_BLOCKSIGHT); /* make the door space a solid tile*/}/********************************** Open or Close a door (Press space at a door) **********************************/void OperateDoor(Word dooron){ Word type; door_t *door; door = &doors[dooron]; /* Which door? */ type = door->info>>1; /* Get the door type */ if ( (type==1 && !(gamestate.keys&1)) || (type==2 && !(gamestate.keys&2)) ) { PlaySound(SND_LOCKEDDOOR); /* The door is locked */ return; } switch (door->action) { case DR_CLOSED: case DR_CLOSING: OpenDoor(door); /* Open the door */ break; case DR_OPEN: case DR_OPENING: CloseDoor(door); /* Close the door */ }}/********************************** Close the door after a few seconds **********************************/void DoorOpen(door_t *door){ door->ticcount+=TicCount; /* Inc the tic value */ if (door->ticcount >= OPENTICS) { /* Time up? */ door->ticcount = OPENTICS-1; /* So if the door can't close it will keep trying*/ CloseDoor(door); /* Try to close the door */ }}/********************************** Step the door animation for open, mark as DR_OPEN if all the way open **********************************/void DoorOpening(door_t *door){ Word position; Word area1,area2; Byte *SoundNumPtr; position = door->position; /* Get the pixel position */ if (!position) { /* Fully closed? */ /* door is just starting to open, so connect the areas*/ SoundNumPtr = MapPtr->areasoundnum; area1 = SoundNumPtr[door->area1]; area2 = SoundNumPtr[door->area2]; AddConnection(area1,area2); /* Link the two together */ ConnectAreas(); /* Link the map */ if (areabyplayer[area1] || areabyplayer[area2]) { /* Can I hear it? */ PlaySound(SND_OPENDOOR); /* Play the door sound */ } }/* slide the door open a bit */ position += DOORSPEED*TicCount; /* Move the door a bit */ if (position >= TILEGLOBAL-1) { /* Fully open? */ /* Door is all the way open */ position = TILEGLOBAL-1; /* Set to maximum */ door->ticcount = 0; /* Reset the timer for closing */ door->action = DR_OPEN; /* Mark as open */ tilemap[door->tiley][door->tilex] &= ~(TI_BLOCKMOVE|TI_BLOCKSIGHT); /* Mark as enterable */ } door->position = position; /* Set the new position */}/********************************** Step the door animation for close, mark as DR_CLOSED if all the way closed **********************************/void DoorClosing(door_t *door){ int position; Byte *SoundNumPtr; position = door->position-(DOORSPEED*TicCount); /* Close a little more */ if (position <= 0) { /* Will I close now? */ /* door is closed all the way, so disconnect the areas*/ SoundNumPtr = MapPtr->areasoundnum; /* Unlink the sound areas */ RemoveConnection(SoundNumPtr[door->area1],SoundNumPtr[door->area2]); ConnectAreas(); /* Reset areabyplayer */ door->action = DR_CLOSED; /* It's closed */ position = 0; /* Mark as closed */ } door->position = position; /* Set the new position */}/********************************** Process all the doors each game loop **********************************/void MoveDoors(void){ Word dooron; /* Which door am I on? */ door_t *door; /* Pointer to current door */ dooron = numdoors; /* How many doors to scan? */ if (dooron) { /* Any doors at all? */ door = doors; /* Pointer to the first door */ do { switch (door->action) { /* Call the action code */ case DR_OPEN: DoorOpen(door); /* Check to close the door */ break; case DR_OPENING: /* Continue the door opening */ DoorOpening(door); break; case DR_CLOSING: /* Close the door */ DoorClosing(door); } ++door; /* Next pointer */ } while (--dooron); /* All doors done? */ }}