#include #include #include #include #include #include "behave.h" SCF_IMPLEMENT_IBASE (BehaviourLayer) SCF_IMPLEMENTS_INTERFACE (iCelBlLayer) SCF_IMPLEMENT_IBASE_END BehaviourLayer::BehaviourLayer (iCelPlLayer* pl) { SCF_CONSTRUCT_IBASE (0); BehaviourLayer::pl = pl; } BehaviourLayer::~BehaviourLayer () { SCF_DESTRUCT_IBASE (); } iCelBehaviour* BehaviourLayer::CreateBehaviour (iCelEntity* entity, const char* name) { iCelBehaviour* behave = 0; if (!strcmp (name, "level_behave")) behave = new BehaviourLevel (entity, this, pl); else if (!strcmp (name, "player_behave")) behave = new BehaviourPlayer (entity, this, pl); else if (!strcmp (name, "box_behave")) behave = new BehaviourBox (entity, this, pl); else if (!strcmp (name, "badone_behave")) behave = new BehaviourBadOne (entity, this, pl); if (behave) { entity->SetBehaviour (behave); // There is now a reference in the entity. We destroy // our own reference here. behave->DecRef (); } return behave; } //----------------------------------------------------------------------------- SCF_IMPLEMENT_IBASE (BehaviourCommon) SCF_IMPLEMENTS_INTERFACE (iCelBehaviour) SCF_IMPLEMENT_IBASE_END BehaviourCommon::BehaviourCommon (iCelEntity* entity, BehaviourLayer* bl, iCelPlLayer* pl) { SCF_CONSTRUCT_IBASE (0); BehaviourCommon::entity = entity; BehaviourCommon::bl = bl; BehaviourCommon::pl = pl; } BehaviourCommon::~BehaviourCommon () { SCF_DESTRUCT_IBASE (); } bool BehaviourCommon::SendMessage (const char* msg_id, iCelPropertyClass* pc, celData& ret, iCelParameterBlock* params, ...) { va_list arg; va_start (arg, params); bool rc = SendMessageV (msg_id, pc, ret, params, arg); va_end (arg); return rc; } bool BehaviourCommon::SendMessageV (const char* msg_id, iCelPropertyClass* pc, celData& ret, iCelParameterBlock* params, va_list arg) { csStringID id = pl->FetchStringID (msg_id); return SendMessage (id, pc, ret, params, arg); } bool BehaviourCommon::SendMessage (csStringID, iCelPropertyClass*, celData&, iCelParameterBlock*, va_list) { return false; } //----------------------------------------------------------------------------- bool BehaviourLevel::SendMessage (csStringID msg_id, iCelPropertyClass* pc, celData& ret, iCelParameterBlock* params, va_list arg) { return BehaviourCommon::SendMessage (msg_id, pc, ret, params, arg); } //----------------------------------------------------------------------------- BehaviourPlayer::BehaviourPlayer (iCelEntity* entity, BehaviourLayer* bl, iCelPlLayer* pl) : BehaviourCommon (entity, bl, pl) { id_pccommandinput_forward1 = pl->FetchStringID ("pccommandinput_forward1"); id_pccommandinput_forward0 = pl->FetchStringID ("pccommandinput_forward0"); id_pccommandinput_backward1 = pl->FetchStringID ("pccommandinput_backward1"); id_pccommandinput_backward0 = pl->FetchStringID ("pccommandinput_backward0"); id_pccommandinput_rotateleft1 = pl->FetchStringID ("pccommandinput_rotateleft1"); id_pccommandinput_rotateleft0 = pl->FetchStringID ("pccommandinput_rotateleft0"); id_pccommandinput_rotateright1 = pl->FetchStringID ("pccommandinput_rotateright1"); id_pccommandinput_rotateright0 = pl->FetchStringID ("pccommandinput_rotateright0"); id_pccommandinput_cammode1 = pl->FetchStringID ("pccommandinput_cammode1"); id_pccommandinput_drop1 = pl->FetchStringID ("pccommandinput_drop1"); id_pcinventory_addchild = pl->FetchStringID ("pcinventory_addchild"); id_pcinventory_removechild = pl->FetchStringID ("pcinventory_removechild"); } void BehaviourPlayer::GetActorMove () { if (!pcactormove) { pcactormove = CEL_QUERY_PROPCLASS_ENT (entity, iPcActorMove); } } void BehaviourPlayer::GetInventory () { if (!pcinventory) { pcinventory = CEL_QUERY_PROPCLASS_ENT (entity, iPcInventory); } } void BehaviourPlayer::GetMesh () { if (!pcmesh) { pcmesh = CEL_QUERY_PROPCLASS_ENT (entity, iPcMesh); } } void BehaviourPlayer::ShowInventory () { size_t count = pcinventory->GetEntityCount (); size_t i; for (i = 0 ; i < count ; i++) { iCelEntity* child = pcinventory->GetEntity (i); printf (" child %d is '%s'\n", i, child->GetName ()); } } void BehaviourPlayer::Drop () { GetInventory (); size_t count = pcinventory->GetEntityCount (); if (count <= 0) { printf ("Inventory is empty!\n"); return; } iCelEntity* child = pcinventory->GetEntity (0); pcinventory->RemoveEntity (child); csRef pclinmove = CEL_QUERY_PROPCLASS_ENT (child, iPcLinearMovement); if (pclinmove) { GetMesh (); // Now we get current position and orientation from player mesh and from that // we calculate a spot in front of the player where we will drop down the item. csVector3 pos = pcmesh->GetMesh ()->GetMovable ()->GetTransform ().This2Other (csVector3 (0, 2, -2)); iSector* sector = pcmesh->GetMesh ()->GetMovable ()->GetSectors ()->Get (0); pclinmove->SetPosition (pos, 0, sector); pclinmove->SetVelocity (csVector3 (0, .1f, 0)); csRef pcmesh_child = CEL_QUERY_PROPCLASS_ENT (child, iPcMesh); if (pcmesh_child) pcmesh_child->Show (); } } bool BehaviourPlayer::SendMessage (csStringID msg_id, iCelPropertyClass* pc, celData& ret, iCelParameterBlock* params, va_list arg) { GetActorMove (); if (msg_id == id_pccommandinput_forward1) pcactormove->Forward (true); else if (msg_id == id_pccommandinput_forward0) pcactormove->Forward (false); else if (msg_id == id_pccommandinput_backward1) pcactormove->Backward (true); else if (msg_id == id_pccommandinput_backward0) pcactormove->Backward (false); else if (msg_id == id_pccommandinput_rotateleft1) pcactormove->RotateLeft (true); else if (msg_id == id_pccommandinput_rotateleft0) pcactormove->RotateLeft (false); else if (msg_id == id_pccommandinput_rotateright1) pcactormove->RotateRight (true); else if (msg_id == id_pccommandinput_rotateright0) pcactormove->RotateRight (false); else if (msg_id == id_pccommandinput_cammode1) pcactormove->ToggleCameraMode (); else if (msg_id == id_pccommandinput_drop1) Drop (); else if (msg_id == id_pcinventory_addchild) { GetInventory (); printf ("Got a new object! Objects in inventory:\n"); ShowInventory (); } else if (msg_id == id_pcinventory_removechild) { GetInventory (); printf ("Object removed from inventory! Objects in inventory:\n"); ShowInventory (); } else return BehaviourCommon::SendMessage (msg_id, pc, ret, params, arg);; return true; } //----------------------------------------------------------------------------- BehaviourBox::BehaviourBox (iCelEntity* entity, BehaviourLayer* bl, iCelPlLayer* pl) : BehaviourCommon (entity, bl, pl) { id_pcmeshsel_down = pl->FetchStringID ("pcmeshsel_down"); GetPlayer (); } void BehaviourBox::PickUp () { if (!player) return; csRef pcinv = CEL_QUERY_PROPCLASS_ENT (player, iPcInventory); if (pcinv) { pcinv->AddEntity (entity); csRef pcmesh = CEL_QUERY_PROPCLASS_ENT (entity, iPcMesh); if (pcmesh) pcmesh->Hide (); } } void BehaviourBox::GetPlayer () { if (!pcmeshsel || !player) { pcmeshsel = CEL_QUERY_PROPCLASS_ENT (entity, iPcMeshSelect); player = pl->FindEntity ("player"); if (!player) return; csRef pccamera = CEL_QUERY_PROPCLASS_ENT (player, iPcCamera); if (pccamera) pcmeshsel->SetCamera (pccamera); } } bool BehaviourBox::SendMessage (csStringID msg_id, iCelPropertyClass* pc, celData& ret, iCelParameterBlock* params, va_list arg) { if (msg_id == id_pcmeshsel_down) { PickUp (); return true; } return BehaviourCommon::SendMessage (msg_id, pc, ret, params, arg); } //----------------------------------------------------------------------------- BehaviourBadOne::BehaviourBadOne (iCelEntity* entity, BehaviourLayer* bl, iCelPlLayer* pl) : BehaviourCommon (entity, bl, pl) { id_pctimer_wakeup = pl->FetchStringID ("pctimer_wakeup"); id_par_elapsedticks = pl->FetchStringID ("cel.parameter.elapsedticks"); ReadPath (); } static bool GetPropVector (iPcProperties* pcprop, const char* prefix, int i, csVector3& v) { csString propname = prefix; propname += i; size_t idx = pcprop->GetPropertyIndex (propname); if (idx == csArrayItemNotFound) return false; if (!pcprop->GetPropertyVector (idx, v)) return false; return true; } static bool GetPropLong (iPcProperties* pcprop, const char* prefix, int i, long& l) { csString propname = prefix; propname += i; size_t idx = pcprop->GetPropertyIndex (propname); if (idx == csArrayItemNotFound) return false; l = pcprop->GetPropertyLong (idx); return true; } void BehaviourBadOne::ReadPath () { csRef pcprop = CEL_QUERY_PROPCLASS_ENT (entity, iPcProperties); // Count the number of points we have. int count = 0; for (;;) { csVector3 v; if (!GetPropVector (pcprop, "pos", count+1, v)) break; count++; } path.AttachNew (new csPath(count)); int i = 0; long totaltime = 0; for (i = 0 ; i < count ; i++) { csVector3 pos, forward, up; GetPropVector (pcprop, "pos", i+1, pos); if (!GetPropVector (pcprop, "forward", i+1, forward)) forward.Set (1, 0, 0); if (!GetPropVector (pcprop, "up", i+1, up)) up.Set (0, 1, 0); long time; if (!GetPropLong (pcprop, "time", i+1, time)) time = 1000; path->SetPositionVector (i, pos); path->SetUpVector (i, up); path->SetForwardVector (i, forward); path->SetTime (i, float (totaltime) / 1000.0); totaltime += time; } csRef pclinmove = CEL_QUERY_PROPCLASS_ENT (entity, iPcLinearMovement); if (pclinmove) { for (i = 0 ; i < count ; i++) { pclinmove->SetPathAction (i, "default"); } } } void BehaviourBadOne::Restart () { csRef pclinmove = CEL_QUERY_PROPCLASS_ENT (entity, iPcLinearMovement); if (pclinmove) { pclinmove->SetPath (path); pclinmove->SetPathTime (0); } } bool BehaviourBadOne::SendMessage (csStringID msg_id, iCelPropertyClass* pc, celData& ret, iCelParameterBlock* params, va_list arg) { if (msg_id == id_pctimer_wakeup) { Restart (); return true; } return BehaviourCommon::SendMessage (msg_id, pc, ret, params, arg); }