void Explosion(int32_t tx, int32_t ty, int32_t level, C4Object *inobj, int32_t iCausedBy, C4Object *pByObj, C4ID idEffect, const char *szEffect) { int32_t grade = BoundBy((level / 10) - 1, 1, 3); // Sound StdStrBuf sound = FormatString("Blast%c", '0' + grade); StartSoundEffect(sound.getData(), false, 100, pByObj); // Check blast containment C4Object *container = inobj; while (container && !container->Def->ContainBlast) container = container->Contained; // Uncontained blast effects if (!container) { // Incinerate landscape if (!Game.Landscape.Incinerate(tx, ty)) if (!Game.Landscape.Incinerate(tx, ty - 10)) if (!Game.Landscape.Incinerate(tx - 5, ty - 5)) Game.Landscape.Incinerate(tx + 5, ty - 5); // Create blast object or particle C4Object *pBlast; C4ParticleDef *pPrtDef = Game.Particles.pBlast; // particle override if (szEffect) { C4ParticleDef *pPrtDef2 = Game.Particles.GetDef(szEffect); if (pPrtDef2) pPrtDef = pPrtDef2; } else if (idEffect) pPrtDef = NULL; // create particle if (pPrtDef) { Game.Particles.Create(pPrtDef, (float)tx, (float)ty, 0.0f, 0.0f, (float)level, 0); if (SEqual2(pPrtDef->Name.getData(), "Blast")) Game.Particles.Cast(Game.Particles.pFSpark, level / 5 + 1, (float)tx, (float)ty, level, level / 2 + 1.0f, 0x00ef0000, level + 1.0f, 0xffff1010); } else if (pBlast = Game.CreateObjectConstruction( idEffect ? idEffect : C4Id("FXB1"), pByObj, iCausedBy, tx, ty + level, FullCon * level / 20)) pBlast->Call(PSF_Activate); } // Blast objects Game.BlastObjects(tx, ty, level, inobj, iCausedBy, pByObj); if (container != inobj) Game.BlastObjects(tx, ty, level, container, iCausedBy, pByObj); if (!container) { // Blast free landscape. After blasting objects so newly mined materials // don't get flinged Game.Landscape.BlastFree(tx, ty, level, grade, iCausedBy); } }
BOOL ObjectComUnGrab(C4Object *cObj) { // Only if pushing, -> stand if (cObj->GetProcedure() == DFA_PUSH) { C4Object *pTarget = cObj->Action.Target; if (ObjectActionStand(cObj)) { if (!cObj->CloseMenu(false)) return FALSE; cObj->Call(PSF_Grab, &C4AulParSet(C4VObj(pTarget), C4VBool(false))); if (pTarget && pTarget->Status && cObj->Status) pTarget->Call(PSF_Grabbed, &C4AulParSet(C4VObj(cObj), C4VBool(false))); return TRUE; } } return FALSE; }
void Smoke(int32_t tx, int32_t ty, int32_t level, DWORD dwClr) { if (Game.Particles.pSmoke) { Game.Particles.Create(Game.Particles.pSmoke, float(tx), float(ty) - level / 2, 0.0f, 0.0f, float(level), dwClr); return; } // User-defined smoke level int32_t SmokeLevel = GetSmokeLevel(); // Enough smoke out there already if (Game.Objects.ObjectCount(C4Id("FXS1")) >= SmokeLevel) return; // Create smoke level = BoundBy<int32_t>(level, 3, 32); C4Object *pObj; if (pObj = Game.CreateObjectConstruction(C4Id("FXS1"), NULL, NO_OWNER, tx, ty, FullCon * level / 32)) pObj->Call(PSF_Activate); }
void C4RoundResults::EvaluateGoals(C4IDList &GoalList, C4IDList &FulfilledGoalList, int32_t iPlayerNumber) { // clear prev GoalList.Clear(); FulfilledGoalList.Clear(); // Items int32_t cnt; C4ID idGoal; for (cnt=0; (idGoal=::Objects.GetListID(C4D_Goal,cnt)); cnt++) { // determine if the goal is fulfilled - do the calls even if the menu is not to be opened to ensure synchronization bool fFulfilled = false;; C4Object *pObj = C4Id2Def(idGoal) ? ::Objects.Find(::Definitions.ID2Def(idGoal)) : NULL; if (pObj) { // Check fulfilled per player, this enables the possibility of rivalry. C4AulParSet pars(iPlayerNumber); fFulfilled = !!pObj->Call(PSF_IsFulfilled, &pars); } GoalList.SetIDCount(idGoal, cnt, true); if (fFulfilled) FulfilledGoalList.SetIDCount(idGoal, 1, true); } }
bool ObjectComUnGrab(C4Object *cObj) { // Only if pushing, -> stand if (cObj->GetProcedure() == DFA_PUSH) { C4Object *pTarget = cObj->Action.Target; if (ObjectActionStand(cObj)) { if (!cObj->CloseMenu(false)) return false; cObj->Call(PSF_Grab, &C4AulParSet(pTarget, false)); // clear action target cObj->Action.Target = nullptr; if (pTarget && pTarget->Status && cObj->Status) { pTarget->Call(PSF_Grabbed, &C4AulParSet(cObj, false)); } return true; } } return false; }