C4SoundEffect* C4SoundSystem::GetEffect(const char *szSndName) { // Remember wildcards before adding .* extension - if there are 2 versions with different file extensions, play the last added bool bRandomSound = SCharCount('?',szSndName) || SCharCount('*',szSndName); // Evaluate sound name char szName[C4MaxSoundName+2+1]; SCopy(szSndName,szName,C4MaxSoundName); // Any extension accepted DefaultExtension(szName,"*"); // Play nth Sound. Standard: 1 int32_t iNumber = 1; // Sound with a wildcard: determine number of available matches if (bRandomSound) { iNumber = 0; // Count matching sounds for (C4SoundEffect *pSfx=FirstSound; pSfx; pSfx=pSfx->Next) if (WildcardMatch(szName,pSfx->Name)) ++iNumber; // Nothing found? Abort if(iNumber == 0) return NULL; iNumber=UnsyncedRandom(iNumber)+1; } // Find requested sound effect in bank C4SoundEffect *pSfx; for (pSfx=FirstSound; pSfx; pSfx=pSfx->Next) if (WildcardMatch(szName,pSfx->Name)) if(!--iNumber) break; return pSfx; // Is still NULL if nothing is found }
C4SoundEffect *C4SoundSystem::GetEffect(const char *szSndName) { C4SoundEffect *pSfx; char szName[C4MaxSoundName + 4 + 1]; int32_t iNumber; // Evaluate sound name SCopy(szSndName, szName, C4MaxSoundName); // Default extension DefaultExtension(szName, "wav"); // Convert old style '*' wildcard to correct '?' wildcard // For sound effects, '*' is supposed to match single digits only SReplaceChar(szName, '*', '?'); // Sound with a wildcard: determine number of available matches if (SCharCount('?', szName)) { // Search global sound file if (!(iNumber = SoundFile.EntryCount(szName))) // Search scenario local files if (!(iNumber = Game.ScenarioFile.EntryCount(szName))) // Search bank loaded sounds if (!(iNumber = EffectInBank(szName))) // None found: failure return NULL; // Insert index to name iNumber = BoundBy(1 + SafeRandom(iNumber), 1, 9); SReplaceChar(szName, '?', '0' + iNumber); } // Find requested sound effect in bank for (pSfx = FirstSound; pSfx; pSfx = pSfx->Next) if (SEqualNoCase(szName, pSfx->Name)) break; // Sound not in bank, try add if (!pSfx) if (!(pSfx = AddEffect(szName))) return NULL; return pSfx; }
int32_t C4TextureMap::LoadMap(C4Group &hGroup, const char *szEntryName, BOOL *pOverloadMaterials, BOOL *pOverloadTextures) { char *bpMap; char szLine[100+1]; int32_t cnt, iIndex, iTextures = 0; // Load text file into memory if (!hGroup.LoadEntry(szEntryName,&bpMap,NULL,1)) return 0; // Scan text buffer lines for (cnt=0; SCopySegment(bpMap,cnt,szLine,0x0A,100); cnt++) if ( (szLine[0]!='#') && (SCharCount('=',szLine)==1) ) { SReplaceChar(szLine,0x0D,0x00); if (Inside<int32_t>( iIndex = strtol(szLine,NULL,10), 0, C4M_MaxTexIndex-1 )) { const char *szMapping = szLine+SCharPos('=',szLine)+1; StdStrBuf Material, Texture; Material.CopyUntil(szMapping, '-'); Texture.Copy(SSearch(szMapping, "-")); if (AddEntry(iIndex, Material.getData(), Texture.getData())) iTextures++; } } else { if (SEqual2(szLine, "OverloadMaterials")) { fOverloadMaterials = TRUE; if(pOverloadMaterials) *pOverloadMaterials = TRUE; } if (SEqual2(szLine, "OverloadTextures")) { fOverloadTextures = TRUE; if(pOverloadTextures) *pOverloadTextures = TRUE; } } // Delete buffer, return entry count delete [] bpMap; fEntriesAdded=false; return iTextures; }
void C4ObjectInfoCore::Default(C4ID n_id, C4DefList *pDefs, const char *cpNames) { // Def C4Def *pDef=NULL; if (pDefs) pDef = pDefs->ID2Def(n_id); // Defaults id=n_id; Participation=1; Rank=0; Experience=0; Rounds=0; DeathCount=0; Birthday=0; TotalPlayingTime=0; SCopy("Clonk",Name,C4MaxName); SCopy("Clonk",TypeName,C4MaxName); sRankName.Copy("Clonk"); sNextRankName.Clear(); NextRankExp=0; DeathMessage[0]='\0'; *PortraitFile=0; Age=0; ExtraData.Reset(); // Type if (pDef) SCopy(pDef->GetName(),TypeName,C4MaxName); // Name if (cpNames) { // Name file reference if (SSearchNoCase(cpNames,C4CFN_Names)) SCopy(GetAName(cpNames),Name,C4MaxName); // Name list else { SCopySegment(cpNames,Random(SCharCount(0x0A,cpNames)),Name,0x0A,C4MaxName+1); SClearFrontBack(Name); SReplaceChar(Name,0x0D,0x00); } if (!Name[0]) SCopy("Clonk",Name,C4MaxName); } #ifdef C4ENGINE if (pDefs) UpdateCustomRanks(pDefs); #endif // Physical Physical.Default(); if (pDef) Physical = pDef->Physical; Physical.PromotionUpdate(Rank); // Old format }
// helper func: Determine whether input text is good for a chat-style-layout // dialog bool IsSmallInputQuery(const char *szInputQuery) { if (!szInputQuery) return true; int32_t w, h; if (SCharCount('|', szInputQuery)) return false; if (!C4GUI::GetRes()->TextFont.GetTextExtent(szInputQuery, w, h, true)) return false; // ??? return w < C4GUI::GetScreenWdt() / 5; }
void C4ObjectInfoCore::Default(C4ID n_id, C4DefList *pDefs, const char *cpNames) { // Def C4Def *pDef=NULL; if (pDefs) pDef = pDefs->ID2Def(n_id); // Defaults id=n_id; Participation=1; Rank=0; Experience=0; Rounds=0; DeathCount=0; Birthday=0; TotalPlayingTime=0; SCopy("Clonk",Name,C4MaxName); SCopy("Clonk",TypeName,C4MaxName); sRankName.Copy("Clonk"); sNextRankName.Clear(); NextRankExp=0; DeathMessage[0]='\0'; Age=0; ExtraData.Reset(); // Type if (pDef) SCopy(pDef->GetName(),TypeName,C4MaxName); // Name if (cpNames) { SCopySegment(cpNames,Random(SCharCount(0x0A,cpNames)),Name,0x0A,C4MaxName+1); SClearFrontBack(Name); SReplaceChar(Name,0x0D,0x00); if (!Name[0]) SCopy("Clonk",Name,C4MaxName); } if (pDefs) UpdateCustomRanks(pDefs); }
ResTable(const char * table): Capacity(int(1.10 * SCharCount('\n', table))), Count(0), Entries(new Entry[Capacity]) { // reduce the capacity so that there is always an empty entry to mark the end of the search for an nonexistant key --Capacity; while (Count < Capacity) { // search '=' const char * pos = table; const char * equalpos = 0; while (*pos && *pos != '\n' && *pos != '\r') { if (*pos == '=') equalpos = pos; ++pos; } if (equalpos) { unsigned int h = Hash(table); // Get a pointer to the bucket Entry * e = &(Entries[h % Capacity]); // Search an empty spot int i = 0; while (*e) { #ifdef _DEBUG if (e->Hash == h) printf("Hash Collision: %d (\"%.50s\")\nSTRINGTABLE WILL BREAK\n", h, table); #endif e = &(Entries[(h + ++i) % Capacity]); } // Fill e->Hash = h; e->Data.CopyUntil(equalpos + 1, *pos); // Compile line feeds ("\n" -> 0D0A) for (i = 0; i < pos - equalpos; ++i) if (e->Data.getMData()[i] == '\\' && e->Data.getMData()[i + 1] == 'n') { e->Data.getMData()[i] = 0x0D; e->Data.getMData()[i + 1] = 0x0A; } // Count! ++Count; } while (*pos == '\n' || *pos == '\r') ++pos; table = pos; if (!*table) break; } }
void C4MapScriptMatTexMask::UnmaskSpec(C4String *spec) { // Mask all indices of material-texture definitions // Possible definitions: // Material-Texture - Given material-texture combination (both sky and tunnel background) // Material - All defined default textures of given material // * - All materials including sky // Sky - Index C4M_MaxTexIndex // Transparent - Index 0 // Background - All tunnel materials plus sky // Liquid - All liquid materials // Solid - All solid materials // Possible modifiers: // ^Material - Given material only with sky background // &Material - Given material only with tunnel background // ~Material - Inverse of given definition; i.e. everything except Material if (!spec || !spec->GetCStr()) return; const char *cspec = spec->GetCStr(); bool invert=false, bgsky=false, bgtunnel=false, prefix_done=false; while (*cspec) { switch (*cspec) { case '~': invert=!invert; break; case '^': bgsky=true; break; case '&': bgtunnel=true; break; default: prefix_done=true; break; } if (prefix_done) break; ++cspec; } std::vector<bool> mat_mask(C4M_MaxTexIndex+1, false); if (SEqual(cspec, DrawFn_Transparent_Name)) { // "Transparent" is zero index. Force to non-IFT mat_mask[0] = true; } else if (SEqual(cspec, DrawFn_Sky_Name)) { // Sky material mat_mask[C4M_MaxTexIndex] = true; } else if (SEqual(cspec, DrawFn_Background_Name)) { // All background materials for (int32_t i=1; i<C4M_MaxTexIndex; ++i) if (!DensitySemiSolid(Landscape.GetPixDensity(i))) mat_mask[i] = true; // Background includes sky mat_mask[C4M_MaxTexIndex] = true; } else if (SEqual(cspec, DrawFn_Liquid_Name)) { // All liquid materials for (int32_t i=1; i<C4M_MaxTexIndex; ++i) if (DensityLiquid(Landscape.GetPixDensity(i))) mat_mask[i] = true; } else if (SEqual(cspec, DrawFn_Solid_Name)) { // All solid materials for (int32_t i=1; i<C4M_MaxTexIndex; ++i) if (DensitySolid(Landscape.GetPixDensity(i))) mat_mask[i] = true; } else if (SEqual(cspec, "*")) { // All materials for (int32_t i=1; i<C4M_MaxTexIndex; ++i) mat_mask[i] = true; // Including sky mat_mask[C4M_MaxTexIndex] = true; } else { // Specified material if (SCharCount('-', cspec)) { // Material+Texture int32_t col = ::MapScript.pTexMap->GetIndexMatTex(cspec, NULL, false); if (col) mat_mask[col] = true; } else { // Only material: Mask all textures of this material int32_t mat = ::MapScript.pMatMap->Get(cspec); if (mat!=MNone) { const char *tex_name; int32_t col; for (int32_t itex=0; (tex_name=::MapScript.pTexMap->GetTexture(itex)); itex++) if ((col = ::MapScript.pTexMap->GetIndex(cspec,tex_name,false))) mat_mask[col] = true; } } } // 'OR' spec onto this->sky_mask and this->tunnel_mask. Apply bgsky, bgtunnel and invert. for (int32_t i=0; i<C4M_MaxTexIndex + 1; ++i) { if ((mat_mask[i] && (bgsky || !bgtunnel)) != invert) sky_mask[i] = true; if ((mat_mask[i] && (!bgsky || bgtunnel)) != invert) tunnel_mask[i] = true; } }
bool C4Sky::Init(bool fSavegame) { int32_t skylistn; // reset scrolling pos+speed // not in savegame, because it will have been loaded from game data there if (!fSavegame) { x=y=xdir=ydir=0; ParX=ParY=10; ParallaxMode=0; } // Check for sky bitmap in scenario file Surface = new C4Surface(); bool loaded = !!Surface->LoadAny(Game.ScenarioFile,C4CFN_Sky,true,true, C4SF_Tileable | C4SF_MipMap); // Else, evaluate scenario core landscape sky default list if (!loaded) { // Scan list sections SReplaceChar(Game.C4S.Landscape.SkyDef,',',';'); // modifying the C4S here...! skylistn=SCharCount(';',Game.C4S.Landscape.SkyDef)+1; char str[402]; SCopySegment(Game.C4S.Landscape.SkyDef,SeededRandom(Game.RandomSeed,skylistn),str,';'); SClearFrontBack(str); // Sky tile specified, try load if (*str && !SEqual(str,"Default")) { // Check for sky tile in scenario file loaded = !!Surface->LoadAny(Game.ScenarioFile,str,true,true, C4SF_Tileable | C4SF_MipMap); if (!loaded) { loaded = !!Surface->LoadAny(::GraphicsResource.Files, str, true, false, C4SF_Tileable | C4SF_MipMap); } } } if (loaded) { // surface loaded, store first color index FadeClr1=FadeClr2=0xffffffff; // set parallax scroll mode switch (Game.C4S.Landscape.SkyScrollMode) { case 0: // default: no scrolling break; case 1: // go with the wind in xdir, and do some parallax scrolling in ydir ParallaxMode=C4SkyPM_Wind; ParY=20; break; case 2: // parallax in both directions ParX=ParY=20; break; } } // Else, try creating default Surface if (!loaded) { SetFadePalette(Game.C4S.Landscape.SkyDefFade); delete Surface; Surface = 0; } // Load sky shaders: regular sprite shaders with OC_SKY define const char* const SkyDefines[] = { "OC_SKY", NULL }; if (!pDraw->PrepareSpriteShader(Shader, "Sky", Surface ? C4SSC_BASE : 0, &::GraphicsResource.Files, SkyDefines, NULL)) return false; if (!pDraw->PrepareSpriteShader(ShaderLight, "SkyLight", (Surface ? C4SSC_BASE : 0) | C4SSC_LIGHT, &::GraphicsResource.Files, SkyDefines, NULL)) return false; // no sky - using fade in newgfx if (!Surface) return true; // Store size if (Surface) { int iWdt,iHgt; if (Surface->GetSurfaceSize(iWdt, iHgt)) { Width = iWdt; Height = iHgt; } } // Success return true; }