diff --git a/constants.h b/constants.h index c623670..36b7e75 100644 --- a/constants.h +++ b/constants.h @@ -39,7 +39,7 @@ /** Melee and close-up attack range, in RCL_Units. */ -#define SFG_MELEE_RANGE 1400 +#define SFG_MELEE_RANGE 1600 /** Player's melee hit range, in RCL_Units (RCL_UNITS_PER_SQUARE means full angle, @@ -79,7 +79,7 @@ Distance at which level elements (sprites) collide, in RCL_Unit (1024 per square). */ -#define SFG_ELEMENT_COLLISION_DISTANCE 800 +#define SFG_ELEMENT_COLLISION_DISTANCE 2048 /** Height, in RCL_Units, at which collisions happen with level elements @@ -91,7 +91,7 @@ Distance at which explosion does damage and throws away the player and monsters, in RCL_Units. */ -#define SFG_EXPLOSION_DISTANCE 2048 +#define SFG_EXPLOSION_DISTANCE 2048 /** Maximum player health. diff --git a/main.c b/main.c index feeede2..7f40e3a 100755 --- a/main.c +++ b/main.c @@ -143,6 +143,10 @@ typedef uint8_t SFG_ItemRecord; #define SFG_ITEM_RECORD_ACTIVE_MASK 0x80 +#define SFG_ITEM_RECORD_LEVEL_ELEMENT(itemRecord) \ + (SFG_currentLevel.levelPointer->elements[itemRecord & \ + ~SFG_ITEM_RECORD_ACTIVE_MASK]) + typedef struct { uint8_t stateType; /**< Holds state (lower 4 bits) and type of monster @@ -341,10 +345,10 @@ uint8_t SFG_getDamageValue(uint8_t attackType) return value; } -static inline RCL_Unit - SFG_taxicabDistance(RCL_Unit x0, RCL_Unit y0, RCL_Unit x1, RCL_Unit y1) +RCL_Unit SFG_taxicabDistance( + RCL_Unit x0, RCL_Unit y0, RCL_Unit z0, RCL_Unit x1, RCL_Unit y1, RCL_Unit z1) { - return RCL_absVal(x0 - x1) + RCL_absVal(y0 - y1); + return (RCL_absVal(x0 - x1) + RCL_absVal(y0 - y1) + RCL_absVal(z0 - z1)); } static inline uint8_t SFG_RCLUnitToZBuffer(RCL_Unit x) @@ -1277,18 +1281,51 @@ void SFG_createExplosion(RCL_Unit x, RCL_Unit y, RCL_Unit z) { SFG_MonsterRecord *monster = &(SFG_currentLevel.monsterRecords[i]); - if ( - (SFG_MR_STATE(*monster) != SFG_MONSTER_STATE_INACTIVE) && - (RCL_absVal(SFG_MONSTER_COORD_TO_RCL_UNITS(monster->coords[0]) - x) <= - SFG_EXPLOSION_DISTANCE) && - (RCL_absVal(SFG_MONSTER_COORD_TO_RCL_UNITS(monster->coords[1]) - y) <= - SFG_EXPLOSION_DISTANCE) - ) + if (SFG_MR_STATE(*monster) == SFG_MONSTER_STATE_INACTIVE) + continue; + + RCL_Unit monsterHeight = + SFG_floorHeightAt( + SFG_MONSTER_COORD_TO_SQUARES(monster->coords[0]), + SFG_MONSTER_COORD_TO_SQUARES(monster->coords[1])) + + RCL_UNITS_PER_SQUARE / 2; + + if (SFG_taxicabDistance( + SFG_MONSTER_COORD_TO_RCL_UNITS(monster->coords[0]), + SFG_MONSTER_COORD_TO_RCL_UNITS(monster->coords[1]),monsterHeight, + x,y,z) <= SFG_EXPLOSION_DISTANCE) { SFG_monsterChangeHealth(monster, -1 * SFG_getDamageValue(SFG_WEAPON_FIRE_TYPE_FIREBALL)); } } + + // explode other barrels + + for (uint16_t i = 0; i < SFG_currentLevel.itemRecordCount; ++i) + { + SFG_ItemRecord item = SFG_currentLevel.itemRecords[i]; + + if (!(item & SFG_ITEM_RECORD_ACTIVE_MASK)) + continue; + + SFG_LevelElement element = SFG_ITEM_RECORD_LEVEL_ELEMENT(item); + + if (element.type != SFG_LEVEL_ELEMENT_BARREL) + continue; + + RCL_Unit elementHeight = + SFG_floorHeightAt(element.coords[0],element.coords[1]); + + if (SFG_taxicabDistance( + x,y,z, + element.coords[0] * RCL_UNITS_PER_SQUARE + RCL_UNITS_PER_SQUARE / 2, + element.coords[1] * RCL_UNITS_PER_SQUARE + RCL_UNITS_PER_SQUARE / 2, + elementHeight) <= SFG_EXPLOSION_DISTANCE) + { + // TODO: explode + } + } } void SFG_createDust(RCL_Unit x, RCL_Unit y, RCL_Unit z) @@ -1311,14 +1348,6 @@ void SFG_createDust(RCL_Unit x, RCL_Unit y, RCL_Unit z) SFG_createProjectile(dust); } -uint8_t SFG_isInMeleeRange(RCL_Unit x0, RCL_Unit y0, RCL_Unit z0, RCL_Unit x1, - RCL_Unit y1, RCL_Unit z1) -{ - return - (SFG_taxicabDistance(x0,y0,x1,y1) <= SFG_MELEE_RANGE) && - (RCL_absVal(z0 - z1) <= SFG_MELEE_RANGE); -} - void SFG_getMonsterWorldPosition(SFG_MonsterRecord *monster, RCL_Unit *x, RCL_Unit *y, RCL_Unit *z) { @@ -1427,14 +1456,10 @@ void SFG_monsterPerformAI(SFG_MonsterRecord *monster) SFG_getMonsterWorldPosition(monster,&pX,&pY,&pZ); uint8_t isClose = // close to player? - SFG_isInMeleeRange( - pX, - pY, - pZ, - SFG_player.camera.position.x, - SFG_player.camera.position.y, - SFG_player.camera.height - ); + SFG_taxicabDistance(pX,pY,pZ, + SFG_player.camera.position.x, + SFG_player.camera.position.y, + SFG_player.camera.height) <= SFG_MELEE_RANGE; if (!isClose) { @@ -1612,15 +1637,8 @@ static inline uint8_t SFG_elementCollides( ) { return - ( - SFG_taxicabDistance(pointX,pointY,elementX,elementY) - <= (SFG_ELEMENT_COLLISION_DISTANCE + widthMargin) - ) - && - ( - (pointZ - heightMargin - elementHeight) - <= SFG_ELEMENT_COLLISION_HEIGHT - ); + SFG_taxicabDistance(pointX,pointY,pointZ,elementX,elementY,elementHeight) + <= (SFG_ELEMENT_COLLISION_DISTANCE + widthMargin); } /** @@ -1724,10 +1742,10 @@ void SFG_gameStep() RCL_Unit pX, pY, pZ; SFG_getMonsterWorldPosition(m,&pX,&pY,&pZ); - if (!SFG_isInMeleeRange(pX,pY,pZ, - SFG_player.camera.position.x, - SFG_player.camera.position.y, - SFG_player.camera.height)) + if (SFG_taxicabDistance(pX,pY,pZ, + SFG_player.camera.position.x, + SFG_player.camera.position.y, + SFG_player.camera.height) > SFG_MELEE_RANGE) continue; RCL_Vector2D toMonster; @@ -1930,8 +1948,7 @@ void SFG_gameStep() SFG_floorHeightAt( SFG_MONSTER_COORD_TO_SQUARES(m->coords[0]), SFG_MONSTER_COORD_TO_SQUARES(m->coords[1])), - RCL_CAMERA_COLL_RADIUS / 2, - RCL_CAMERA_COLL_HEIGHT_BELOW + 0,0 ) ) { @@ -1964,8 +1981,7 @@ void SFG_gameStep() ePos.x, ePos.y, SFG_floorHeightAt(e->coords[0],e->coords[1]), - RCL_CAMERA_COLL_RADIUS / 2, - RCL_CAMERA_COLL_HEIGHT_BELOW + 0,0 ) ) {