void Splash(int32_t tx, int32_t ty, int32_t amt, C4Object *pByObj) { // Splash only if there is free space above if (GBackSemiSolid(tx, ty - 15)) return; // get back mat int32_t iMat = GBackMat(tx, ty); // check liquid if (MatValid(iMat)) if (DensityLiquid(Game.Material.Map[iMat].Density) && Game.Material.Map[iMat].Instable) { int32_t sy = ty; while (GBackLiquid(tx, sy) && sy > ty - 20 && sy >= 0) sy--; // Splash bubbles and liquid for (int32_t cnt = 0; cnt < amt; cnt++) { BubbleOut(tx + Random(16) - 8, ty + Random(16) - 6); if (GBackLiquid(tx, ty) && !GBackSemiSolid(tx, sy)) Game.PXS.Create(Game.Landscape.ExtractMaterial(tx, ty), itofix(tx), itofix(sy), FIXED100(Random(151) - 75), FIXED100(-Random(200))); } } // Splash sound if (amt >= 20) StartSoundEffect("Splash2", false, 100, pByObj); else if (amt > 1) StartSoundEffect("Splash1", false, 100, pByObj); }
BOOL SellFromBase(int32_t iPlr, C4Object *pBaseObj, C4ID id, C4Object *pSellObj) { C4Object *pThing; // Valid checks if (!ValidPlr(iPlr)) return FALSE; if (!pBaseObj || !ValidPlr(pBaseObj->Base)) return FALSE; if (~Game.C4S.Game.Realism.BaseFunctionality & BASEFUNC_Sell) return FALSE; // Base owner eliminated if (Game.Players.Get(pBaseObj->Base)->Eliminated) { StartSoundEffect("Error",false,100,pBaseObj); sprintf(OSTR,LoadResStr("IDS_PLR_ELIMINATED"),Game.Players.Get(pBaseObj->Base)->GetName()); GameMsgPlayer(OSTR,iPlr); return FALSE; } // Base owner hostile if (Hostile(iPlr,pBaseObj->Base)) { StartSoundEffect("Error",false,100,pBaseObj); sprintf(OSTR,LoadResStr("IDS_PLR_HOSTILE"),Game.Players.Get(pBaseObj->Base)->GetName()); GameMsgPlayer(OSTR,iPlr); return FALSE; } // check validity of sell object, if specified if (pThing = pSellObj) if (!pThing->Status || pThing->Contained != pBaseObj) pThing = NULL; // Get object from home pBaseObj via selected id, if no or an anvalid thing has been specified if (!pThing) if (!(pThing=pBaseObj->Contents.Find(id))) return FALSE; // check definition NoSell if (pThing->Def->NoSell) return FALSE; // Sell object (pBaseObj owner gets the money) return Game.Players.Get(pBaseObj->Base)->Sell2Home(pThing); }
void Splash(int32_t tx, int32_t ty, int32_t amt, C4Object *pByObj) { // Splash only if there is free space above if (GBackSemiSolid(tx, ty - 15)) return; // get back mat int32_t iMat = GBackMat(tx, ty); // check liquid if (MatValid(iMat)) if (DensityLiquid(::MaterialMap.Map[iMat].Density) && ::MaterialMap.Map[iMat].Instable) { int32_t sy = ty; while (GBackLiquid(tx, sy) && sy > ty - 20 && sy >= 0) sy--; // Splash bubbles and liquid for (int32_t cnt=0; cnt<amt; cnt++) { int32_t bubble_x = tx+Random(16)-8; int32_t bubble_y = ty+Random(16)-6; BubbleOut(bubble_x,bubble_y); if (GBackLiquid(tx,ty) && !GBackSemiSolid(tx, sy)) { C4Real xdir = C4REAL100(Random(151)-75); C4Real ydir = C4REAL100(-Random(200)); ::PXS.Create(::Landscape.ExtractMaterial(tx,ty,false), itofix(tx),itofix(sy), xdir, ydir); } } } // Splash sound if (amt>=20) StartSoundEffect("Splash2",false,100,pByObj); else if (amt>1) StartSoundEffect("Splash1",false,100,pByObj); }
C4SoundInstance *StartSoundEffectAt(const char *szSndName, int32_t iX, int32_t iY, int32_t iVolume, int32_t iCustomFallofDistance, int32_t iPitch, C4SoundModifier *modifier) { // Sound check if (!Config.Sound.RXSound) return NULL; // Create C4SoundInstance *pInst = StartSoundEffect(szSndName, false, iVolume, NULL, iCustomFallofDistance, iPitch, modifier); // Set volume by position if (pInst) pInst->SetVolumeByPos(iX, iY); // Return return pInst; }
void SoundLevel(const char *szSndName, C4Object *pObj, int32_t iLevel) { // Sound level zero? Stop if (!iLevel) { StopSoundEffect(szSndName, pObj); return; } // Find or create instance C4SoundInstance *pInst = Application.SoundSystem.FindInstance(szSndName, pObj); if (!pInst) pInst = StartSoundEffect(szSndName, true, iLevel, pObj); if (!pInst) return; // Set volume pInst->SetVolume(iLevel); pInst->Execute(); }
BOOL C4GraphicsSystem::CloseViewport(C4Viewport * cvp) { if (!cvp) return false; /*C4Viewport *next,*prev=NULL; for (C4Viewport *cvp2=FirstViewport; cvp2; cvp2=next) { next=cvp2->Next; if (cvp2 == cvp) { delete cvp; StartSoundEffect("CloseViewport"); if (prev) prev->Next=next; else FirstViewport=next; } else prev=cvp2; }*/ // Chop the start of the chain off if (FirstViewport == cvp) { FirstViewport = cvp->Next; delete cvp; StartSoundEffect("CloseViewport"); } // Take out of the chain else for (C4Viewport * prev = FirstViewport; prev; prev = prev->Next) { if (prev->Next == cvp) { prev->Next = cvp->Next; delete cvp; StartSoundEffect("CloseViewport"); } } // Recalculate viewports RecalculateViewports(); // Done return TRUE; }
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); } }
void C4Object::DirectComContents(C4Object *pTarget, bool fDoCalls) { // safety if (!pTarget || !pTarget->Status || pTarget->Contained != this) return; // Desired object already at front? if (Contents.GetObject() == pTarget) return; // select object via script? if (fDoCalls) if (Call("~ControlContents", &C4AulParSet(pTarget))) return; // default action if (!(Contents.ShiftContents(pTarget))) return; // Selection sound if (fDoCalls) if (!Contents.GetObject()->Call("~Selection", &C4AulParSet(this))) StartSoundEffect("Clonk::Action::Grab",false,100,this); // update menu with the new item in "put" entry if (Menu && Menu->IsActive() && Menu->IsContextMenu()) { Menu->Refill(); } // Done return; }
BOOL Buy2Base(int32_t iPlr, C4Object *pBase, C4ID id, BOOL fShowErrors) { C4Object *pThing; // Validity if (!ValidPlr(iPlr)) return FALSE; if (!pBase || !ValidPlr(pBase->Base)) return FALSE; if (~Game.C4S.Game.Realism.BaseFunctionality & BASEFUNC_Buy) return FALSE; // Base owner hostile if (Hostile(iPlr,pBase->Base)) { if (!fShowErrors) return FALSE; StartSoundEffect("Error",false,100,pBase); sprintf(OSTR,LoadResStr("IDS_PLR_HOSTILE"),Game.Players.Get(pBase->Base)->GetName()); GameMsgPlayer(OSTR,iPlr); return FALSE; } // buy if (!(pThing=Game.Players.Get(pBase->Base)->Buy(id, fShowErrors, iPlr, pBase))) return FALSE; // Object enter target object pThing->Enter(pBase); // Success return TRUE; }
BOOL C4GraphicsSystem::CreateViewport(int32_t iPlayer, bool fSilent) { // Create and init new viewport, add to viewport list int32_t iLastCount = GetViewportCount(); C4Viewport *nvp = new C4Viewport; BOOL fOkay = FALSE; if (Application.isFullScreen) fOkay = nvp->Init(iPlayer, false); else fOkay = nvp->Init(&Console,&Application,iPlayer); if (!fOkay) { delete nvp; return FALSE; } C4Viewport *pLast; for (pLast=FirstViewport; pLast && pLast->Next; pLast=pLast->Next); if (pLast) pLast->Next=nvp; else FirstViewport=nvp; // Recalculate viewports RecalculateViewports(); // Viewports start off at centered position nvp->CenterPosition(); // Action sound if (GetViewportCount()!=iLastCount) if (!fSilent) StartSoundEffect("CloseViewport"); return TRUE; }
BOOL C4GraphicsSystem::CloseViewport(int32_t iPlayer, bool fSilent) { // Close all matching viewports int32_t iLastCount = GetViewportCount(); C4Viewport *next,*prev=NULL; for (C4Viewport *cvp=FirstViewport; cvp; cvp=next) { next=cvp->Next; if (cvp->Player==iPlayer || (iPlayer==NO_OWNER && cvp->fIsNoOwnerViewport)) { delete cvp; if (prev) prev->Next=next; else FirstViewport=next; } else prev=cvp; } // Recalculate viewports RecalculateViewports(); // Action sound if (GetViewportCount()!=iLastCount) if (!fSilent) StartSoundEffect("CloseViewport"); return TRUE; }
BOOL ObjectComLineConstruction(C4Object *cObj) { C4Object *linekit,*tstruct,*cline; DWORD ocf; ObjectActionStand(cObj); // Check physical if (!cObj->GetPhysical()->CanConstruct) { sprintf(OSTR,LoadResStr("IDS_OBJ_NOLINECONSTRUCT"),cObj->GetName()); GameMsgObject(OSTR,cObj); return FALSE; } // - - - - - - - - - - - - - - - - - - Line pickup - - - - - - - - - - - - - - - - - // Check for linekit if (!(linekit=cObj->Contents.Find(C4ID_Linekit))) { // Check for collection limit if (cObj->Def->CollectionLimit && (cObj->Contents.ObjectCount()>=cObj->Def->CollectionLimit) ) return FALSE; // Check line pickup ocf=OCF_LineConstruct; tstruct=Game.Objects.AtObject(cObj->x,cObj->y,ocf,cObj); if (!tstruct || !(ocf & OCF_LineConstruct)) return FALSE; if (!(cline=Game.FindObject(C4ID_None,0,0,0,0,OCF_All,"Connect",tstruct))) return FALSE; // Check line connected to linekit at other end if ( (cline->Action.Target && (cline->Action.Target->Def->id==C4ID_Linekit)) || (cline->Action.Target2 && (cline->Action.Target2->Def->id==C4ID_Linekit)) ) { StartSoundEffect("Error",false,100,cObj); sprintf(OSTR,LoadResStr("IDS_OBJ_NODOUBLEKIT"),cline->GetName()); GameMsgObject(OSTR,cObj); return FALSE; } // Create new linekit if (!(linekit=Game.CreateObject(C4ID_Linekit,cObj,cline->Owner))) return FALSE; // Enter linekit into clonk bool fRejectCollect; if (!linekit->Enter(cObj, TRUE, true, &fRejectCollect)) { // Enter failed: abort operation linekit->AssignRemoval(); return FALSE; } // Attach line to collected linekit StartSoundEffect("Connect",false,100,cObj); if (cline->Action.Target==tstruct) cline->Action.Target=linekit; if (cline->Action.Target2==tstruct) cline->Action.Target2=linekit; // Message sprintf(OSTR,LoadResStr("IDS_OBJ_DISCONNECT"),cline->GetName(),tstruct->GetName()); GameMsgObject(OSTR,tstruct); return TRUE; } // - - - - - - - - - - - - - - - Active construction - - - - - - - - - - - - - - - - - // Active line construction if (cline=Game.FindObject(C4ID_None,0,0,0,0,OCF_All,"Connect",linekit)) { // Check for structure connection ocf=OCF_LineConstruct; tstruct=Game.Objects.AtObject(cObj->x,cObj->y,ocf,cObj); // No structure if (!tstruct || !(ocf & OCF_LineConstruct)) { // No connect StartSoundEffect("Error",false,100,cObj); sprintf(OSTR,LoadResStr("IDS_OBJ_NOCONNECT")); GameMsgObject(OSTR,cObj); return FALSE; } // Check short circuit -> removal if ((cline->Action.Target==tstruct) || (cline->Action.Target2==tstruct)) { StartSoundEffect("Connect",false,100,cObj); sprintf(OSTR,LoadResStr("IDS_OBJ_LINEREMOVAL"),cline->GetName()); GameMsgObject(OSTR,tstruct); cline->AssignRemoval(); return TRUE; } // Check for correct connection type BOOL connect_okay=FALSE; switch (cline->Def->Line) { case C4D_Line_Power: if (tstruct->Def->LineConnect & C4D_Power_Input) connect_okay=TRUE; if (tstruct->Def->LineConnect & C4D_Power_Output) connect_okay=TRUE; break; case C4D_Line_Source: if (tstruct->Def->LineConnect & C4D_Liquid_Output) connect_okay=TRUE; break; case C4D_Line_Drain: if (tstruct->Def->LineConnect & C4D_Liquid_Input) connect_okay=TRUE; break; default: return FALSE; // Undefined line type } if (!connect_okay) { StartSoundEffect("Error",false,100,cObj); sprintf(OSTR,LoadResStr("IDS_OBJ_NOCONNECTTYPE"),cline->GetName(),tstruct->GetName()); GameMsgObject(OSTR,tstruct); return FALSE; } // Connect line to structure StartSoundEffect("Connect",false,100,cObj); if (cline->Action.Target==linekit) cline->Action.Target=tstruct; if (cline->Action.Target2==linekit) cline->Action.Target2=tstruct; linekit->Exit(); linekit->AssignRemoval(); sprintf(OSTR,LoadResStr("IDS_OBJ_CONNECT"),cline->GetName(),tstruct->GetName()); GameMsgObject(OSTR,tstruct); return TRUE; } // - - - - - - - - - - - - - - - - New line - - - - - - - - - - - - - - - - - - - - - // Check for new structure connection ocf=OCF_LineConstruct; tstruct=Game.Objects.AtObject(cObj->x,cObj->y,ocf,cObj); if (!tstruct || !(ocf & OCF_LineConstruct)) { StartSoundEffect("Error",false,100,cObj); sprintf(OSTR,LoadResStr("IDS_OBJ_NONEWLINE")); GameMsgObject(OSTR,cObj); return FALSE; } // Determine new line type C4ID linetype=C4ID_None; // Check source pipe if (linetype==C4ID_None) if (tstruct->Def->LineConnect & C4D_Liquid_Pump) if (!Game.FindObject(C4ID_SourcePipe,0,0,0,0,OCF_All,"Connect",tstruct)) linetype = C4ID_SourcePipe; // Check drain pipe if (linetype==C4ID_None) if (tstruct->Def->LineConnect & C4D_Liquid_Output) if (!Game.FindObject(C4ID_DrainPipe,0,0,0,0,OCF_All,"Connect",tstruct)) linetype = C4ID_DrainPipe; // Check power if (linetype==C4ID_None) if (tstruct->Def->LineConnect & C4D_Power_Output) linetype = C4ID_PowerLine; // No good if (linetype==C4ID_None) { StartSoundEffect("Error",false,100,cObj); sprintf(OSTR,LoadResStr("IDS_OBJ_NONEWLINE")); GameMsgObject(OSTR,cObj); return FALSE; } // Create new line C4Object *newline=CreateLine(linetype,cObj->Owner, tstruct,linekit); if (!newline) return FALSE; StartSoundEffect("Connect",false,100,cObj); sprintf(OSTR,LoadResStr("IDS_OBJ_NEWLINE"),newline->GetName()); GameMsgObject(OSTR,tstruct); return TRUE; }
void GUISound(const char *szSound) { if (Config.Sound.FESamples) StartSoundEffect(szSound); }
int32_t FnFxFireStart(C4AulContext *ctx, C4Object *pObj, int32_t iNumber, int32_t iTemp, int32_t iCausedBy, bool fBlasted, C4Object *pIncineratingObject) { // safety if (!pObj) return -1; // temp readd if (iTemp) { pObj->SetOnFire(true); return 1; } // fail if already on fire if (pObj->GetOnFire()) return -1; // get associated effect C4Effect *pEffect; if (!(pEffect = pObj->pEffects)) return -1; if (!(pEffect = pEffect->Get(iNumber, true))) return -1; // structures must eject contents now, because DoCon is not guaranteed to be // executed! // In extinguishing material BOOL fFireCaused = TRUE; int32_t iMat; if (MatValid(iMat = GBackMat(pObj->x, pObj->y))) if (Game.Material.Map[iMat].Extinguisher) { // blasts should changedef in water, too! if (fBlasted) if (pObj->Def->BurnTurnTo != C4ID_None) pObj->ChangeDef(pObj->Def->BurnTurnTo); // no fire caused fFireCaused = FALSE; } // BurnTurnTo if (fFireCaused) if (pObj->Def->BurnTurnTo != C4ID_None) pObj->ChangeDef(pObj->Def->BurnTurnTo); // eject contents C4Object *cobj; if (!pObj->Def->IncompleteActivity && !pObj->Def->NoBurnDecay) while (cobj = pObj->Contents.GetObject()) { cobj->Controller = iCausedBy; // update controller, so incinerating a hut // full of flints attributes the damage to // the incinerator if (pObj->Contained) cobj->Enter(pObj->Contained); else cobj->Exit(cobj->x, cobj->y); } // Detach attached objects cobj = 0; if (!pObj->Def->IncompleteActivity && !pObj->Def->NoBurnDecay) while (cobj = Game.FindObject(0, 0, 0, 0, 0, OCF_All, 0, pObj, 0, 0, ANY_OWNER, cobj)) if ((cobj->Action.Act > ActIdle) && (cobj->Def->ActMap[cobj->Action.Act].Procedure == DFA_ATTACH)) cobj->SetAction(ActIdle); // fire caused? if (!fFireCaused) { // if object was blasted but not incinerated (i.e., inside extinguisher) // do a script callback if (fBlasted) pObj->Call(PSF_IncinerationEx, &C4AulParSet(C4VInt(iCausedBy))); return -1; } // determine fire appearance int32_t iFireMode; if (!(iFireMode = pObj->Call(PSF_FireMode).getInt())) { // set default fire modes DWORD dwCat = pObj->Category; if (dwCat & (C4D_Living | C4D_StaticBack)) // Tiere, Bäume iFireMode = C4Fx_FireMode_LivingVeg; else if (dwCat & (C4D_Structure | C4D_Vehicle)) // Gebäude und Fahrzeuge // sind unten meist kantig iFireMode = C4Fx_FireMode_StructVeh; else iFireMode = C4Fx_FireMode_Object; } else if (!Inside<int32_t>(iFireMode, 1, C4Fx_FireMode_Last)) { DebugLogF("Warning: FireMode %d of object %s (%s) is invalid!", iFireMode, pObj->GetName(), pObj->Def->GetName()); iFireMode = C4Fx_FireMode_Object; } // store causes in effect vars FxFireVarMode(pEffect).SetInt(iFireMode); FxFireVarCausedBy(pEffect) .SetInt(iCausedBy); // used in C4Object::GetFireCause and timer! FxFireVarBlasted(pEffect).SetBool(fBlasted); FxFireVarIncineratingObj(pEffect).SetObject(pIncineratingObject); // Set values pObj->SetOnFire(true); pObj->FirePhase = Random(MaxFirePhase); if (pObj->Shape.Wdt * pObj->Shape.Hgt > 500) StartSoundEffect("Inflame", false, 100, pObj); if (pObj->Def->Mass >= 100) StartSoundEffect("Fire", true, 100, pObj); // Engine script call pObj->Call(PSF_Incineration, &C4AulParSet(C4VInt(iCausedBy))); // Done, success return C4Fx_OK; }