File WfDebris.c
File List > entities > WfDebris.c
Go to the documentation of this file
#include "WfDebris.h"
#include "BinarySerializer.h"
#include "Entities.h"
#include "Game2DLayer.h"
#include "WfGameLayerData.h"
#include "ObjectPool.h"
#include "Log.h"
#include "AssertLib.h"
#include "WfEntities.h"
#include "GameFramework.h"
#include "WfEntityMessages.h"
#include "ZzFX.h"
#include "Audio.h"
#include "WfTileLayers.h"
struct ZZFXSound gWrongDamageTypeSFX = {1.0,0.05,55.748,0.066,0.252,0.447,0,1.0,0.0,0.0,0.0,0.0,0.062,1.633,0.0,0.333,0.433,0.309,0.171,0.057,0.0};
struct ZZFXSound gPickaxeHitRockSFX = {1.0,0.05,62.25,0.011,0.133,0.298,3,1.0,1.503,0.0,0.0,0.0,0.29,1.191,0.0,0.619,0.0,0.485,0.2,0.0,-2357.049};
struct ZZFXSound gDestroyRockSFX = {1.0,0.05,88.199,0.028,0.125,0.42,5,1.0,0.0,4.522,0.0,0.0,0.0,0.359,6.641019,0.816,0.0,0.423,0.166,0.0,0.0};
struct ZZFXSound gLogHitSFX = {1.0,0.05,63.14,0.049,0.086,0.203,2,1.0,3.678,-4.693,0.0,0.0,0.261,0.185,0.0,0.699,0.0,0.388,0.108,0.087,0.0};
struct ZZFXSound gLogDestroySFX = {1.0,0.05,590.6,0.005,0.28,0.257,1,1.0,0.0,0.0,-196.86,0.159,0.165,0.12,15.624050000000004,0.168,0.0,0.635,0.227,0.421,0.0};
struct WfDebrisData
{
int xTile, yTile;
struct WfDebrisDef def;
vec2 groundContactPoint;
};
static OBJECT_POOL(struct WfDebrisData) gDebrisDataPool = NULL;
static void RockOnDestroy(struct Entity2D* pEnt, struct GameFrameworkLayer* pData)
{
FreeObjectPoolIndex(gDebrisDataPool, pEnt->user.hData);
Entity2DOnDestroy(pEnt, pData);
}
void WfDebrisGetGroundContactPoint(struct Entity2D* pEnt, vec2 outPoint)
{
struct WfDebrisData* pData = &gDebrisDataPool[pEnt->user.hData];
outPoint[0] = pData->groundContactPoint[0];
outPoint[1] = pData->groundContactPoint[1];
}
static void DebrisHandleEntityMsg(struct Entity2D* pEnt, struct Entity2D* pSender, struct EntityToEntityMessage* pMsg, struct GameFrameworkLayer* pLayer)
{
struct GameLayer2DData* pGameLayerData = pLayer->userData;
struct WfDebrisData* pData = &gDebrisDataPool[pEnt->user.hData];
switch(pMsg->type)
{
case E2EM_Damage:
{
struct WfDamageMsg* pDamageMessage = WfGetDamageMessage(pMsg);
switch (pDamageMessage->type)
{
case WfPickaxeDamage:
if(pData->def.type == WfRockType1 || pData->def.type == WfRockType2)
{
pData->def.health -= pDamageMessage->damage;
if(pData->def.health <= 0)
{
Et2D_DestroyEntity(pLayer, &pGameLayerData->entities, pEnt->thisEntity);
pGameLayerData->bCurrentLocationIsDirty = true;
Au_PlayZzFX(&gDestroyRockSFX);
}
else
{
Au_PlayZzFX(&gPickaxeHitRockSFX);
}
}
else
{
Au_PlayZzFX(&gWrongDamageTypeSFX);
}
break;
case WfAxeDamage:
if(pData->def.type == WfLogType1)
{
pData->def.health -= pDamageMessage->damage;
if(pData->def.health <= 0)
{
Et2D_DestroyEntity(pLayer, &pGameLayerData->entities, pEnt->thisEntity);
pGameLayerData->bCurrentLocationIsDirty = true;
Au_PlayZzFX(&gLogDestroySFX);
}
else
{
Au_PlayZzFX(&gLogHitSFX);
}
}
else
{
Au_PlayZzFX(&gWrongDamageTypeSFX);
}
break;
}
}
break;
};
}
void WfMakeEntityIntoDebrisBasedAt(struct Entity2D* pEnt, int xTile, int yTile, struct WfDebrisDef* def, struct GameLayer2DData* pGameLayerData)
{
if(!gDebrisDataPool)
{
gDebrisDataPool = NEW_OBJECT_POOL(struct WfDebrisData, 64);
}
memset(pEnt, 0, sizeof(struct Entity2D));
pEnt->transform.position[0] = xTile * 32.0f;
pEnt->transform.position[1] = yTile * 32.0f;
pEnt->transform.scale[0] = 1.0f;
pEnt->transform.scale[1] = 1.0f;
pEnt->transform.rotation = 0.0f;
pEnt->transform.rotationPointRelative[0] = 0.0f;
pEnt->transform.rotationPointRelative[1] = 0.0f;
pEnt->bKeepInQuadtree = true;
pEnt->bKeepInDynamicList = false;
pEnt->type = WfEntityType_Rock;
pEnt->numComponents = 0;
struct Component2D* pComponent1 = &pEnt->components[pEnt->numComponents++];
struct Component2D* pComponent2 = &pEnt->components[pEnt->numComponents++];
struct WfSprites* pSprites = &((struct WfGameLayerData*)pGameLayerData->pUserData)->sprites;
TileIndex sprites[3] = {pSprites->debrisSpritesPerSeason[Spring].rock2, pSprites->debrisSpritesPerSeason[Spring].rock1, pSprites->debrisSpritesPerSeason[Spring].debrisWood};
pComponent1->type = ETE_Tiles;
pComponent1->data.tiles.numTiles = 1;
pComponent1->data.tiles.tiles[0].layer = WFLAYER_GROUND2;
pComponent1->data.tiles.tiles[0].x = xTile;
pComponent1->data.tiles.tiles[0].y = yTile;
pComponent1->data.tiles.tiles[0].tile = sprites[def->type];
pComponent2->type = ETE_StaticCollider;
pComponent2->data.staticCollider.shape.type = PBT_Circle;
pComponent2->data.staticCollider.shape.data.circle.center[0] = xTile * 32.0f + 16.0f;//transform2Ground[0];
pComponent2->data.staticCollider.shape.data.circle.center[1] = yTile * 32.0f + 16.0f;//transform2Ground[1];
pComponent2->data.staticCollider.shape.data.circle.radius = 16;
pComponent2->data.staticCollider.bIsSensor = false;
pComponent2->data.staticCollider.onSensorOverlapBegin = NULL;
pComponent2->data.staticCollider.onSensorOverlapEnd = NULL;
pComponent2->data.staticCollider.bGenerateSensorEvents = false;
HGeneric hRockData = NULL_HANDLE;
gDebrisDataPool = GetObjectPoolIndex(gDebrisDataPool, &hRockData);
struct WfDebrisData* pRockData = &gDebrisDataPool[hRockData];
pRockData->def.health = def->health;
pRockData->def.type = def->type;
pRockData->xTile = xTile;
pRockData->yTile = yTile;
pRockData->groundContactPoint[0] = pEnt->transform.position[0];
pRockData->groundContactPoint[1] = pEnt->transform.position[1];
struct WfDebrisData* pData = &gDebrisDataPool[pEnt->user.hData];
struct TileMap* pTM = &pGameLayerData->tilemap;
vec2 addition = {
pTM->layers[pEnt->components[0].data.tiles.tiles[0].layer].tileWidthPx,
pTM->layers[pEnt->components[0].data.tiles.tiles[0].layer].tileHeightPx
};
glm_vec2_add(pRockData->groundContactPoint, addition, pRockData->groundContactPoint);
pEnt->user.hData = hRockData;
Et2D_PopulateCommonHandlers(pEnt);
pEnt->onDestroy = &RockOnDestroy;
pEnt->handleEntityMsg = &DebrisHandleEntityMsg;
pEnt->bSerializeToDisk = true;
pEnt->bSerializeToNetwork = true;
// TODO: Put in the quad tree instead - the quad tree is fucked though.
// re-write the quad tree as a BSP tree as detailed in "Game design patterns"
pEnt->bKeepInQuadtree = true;
pEnt->bKeepInDynamicList = true;
}
HEntity2D WfAddDebrisBasedAt(float x, float y, struct WfDebrisDef* def, struct GameLayer2DData* pGameLayerData)
{
struct Entity2D ent;
WfMakeEntityIntoDebrisBasedAt(&ent, x, y, def, pGameLayerData);
return Et2D_AddEntity(&pGameLayerData->entities, &ent);
}
void WfDeSerializeDebrisEntity(struct BinarySerializer* bs, struct Entity2D* pOutEnt, struct GameLayer2DData* pData)
{
i32 version = 0;
BS_DeSerializeI32(&version, bs);
switch (version)
{
case 1:
{
struct WfDebrisDef def;
int xTile, yTile;
BS_DeSerializeFloat(&def.health, bs);
BS_DeSerializeI32(&def.type, bs);
BS_DeSerializeI32(&xTile, bs);
BS_DeSerializeI32(&yTile, bs);
WfMakeEntityIntoDebrisBasedAt(pOutEnt, xTile, yTile, &def, pData);
}
break;
default:
Log_Error("unknown WfDeSerializeRockEntity version");
EASSERT(false);
break;
}
}
void WfSerializeDebrisEntity(struct BinarySerializer* bs, struct Entity2D* pInEnt, struct GameLayer2DData* pData)
{
struct WfDebrisData* pRockD = &gDebrisDataPool[pInEnt->user.hData];
BS_SerializeI32(1, bs); // version
BS_SerializeFloat(pRockD->def.health, bs);
BS_SerializeI32(pRockD->def.type, bs);
BS_SerializeI32(pRockD->xTile, bs);
BS_SerializeI32(pRockD->yTile, bs);
}