//respawn nameless after he bit the dust void IniSpawn::RespawnNameless() { Game *game = core->GetGame(); Actor *nameless = game->GetPC(0, false); if (NamelessSpawnPoint.isnull()) { core->GetGame()->JoinParty(nameless,JP_INITPOS); NamelessSpawnPoint=nameless->Pos; strnuprcpy(NamelessSpawnArea, nameless->Area, 8); } nameless->Resurrect(); //hardcoded!!! if (NamelessState==36) { nameless->SetStance(IE_ANI_PST_START); } int i; for (i=0;i<game->GetPartySize(false);i++) { MoveBetweenAreasCore(game->GetPC(i, false),NamelessSpawnArea,NamelessSpawnPoint,-1, true); } //certain variables are set when nameless dies for (i=0;i<namelessvarcount;i++) { SetVariable(game, NamelessVar[i].Name,"GLOBAL", NamelessVar[i].Value); } }
void VEFObject::Load2DA(const ieResRef resource) { Init(); AutoTable tab(resource); if (!tab) { return; } SingleObject = false; strnlwrcpy(ResName, resource, 8); ieDword GameTime = core->GetGame()->GameTime; int rows = tab->GetRowCount(); while(rows--) { Point offset; int delay, duration; ieResRef resource; offset.x=atoi(tab->QueryField(rows,0)); offset.y=atoi(tab->QueryField(rows,1)); delay = atoi(tab->QueryField(rows,3)); duration = atoi(tab->QueryField(rows,4)); strnuprcpy(resource, tab->QueryField(rows,2), 8); AddEntry(resource, delay, duration, offset, VEF_VVC, GameTime); } }
void Spell::AddCastingGlow(EffectQueue *fxqueue, ieDword duration, int gender) { char g, t; Effect *fx; ieResRef Resource; int cgsound = CastingSound; if (cgsound>=0 && duration > 1) { //bg2 style if(cgsound&0x100) { //if duration is less than 3, use only the background sound g = 's'; if (duration>3) { switch(gender) { //selection of these sounds is almost purely on whim //though the sounds of devas/demons are probably better this way //all other cases (mostly elementals/animals) don't have sound //externalise if you don't mind another 2da case SEX_MALE: case SEX_SUMMON_DEMON: g = 'm'; break; case SEX_FEMALE: case SEX_BOTH: g = 'f'; break; } } } else { //how style, no pure background sound switch(gender) { default: g = 'm'; break; case SEX_FEMALE: g = 'f'; break; } } if (SpellType==IE_SPL_PRIEST) { t = 'p'; } else { t = 'm'; } //check if bg1 if (!core->HasFeature(GF_CASTING_SOUNDS) && !core->HasFeature(GF_CASTING_SOUNDS2)) { ieResRef s; snprintf(s, 9, "CAS_P%c%01d%c", t, cgsound&0xff, g); strnuprcpy(Resource, s, sizeof(ieResRef)-1); } else { snprintf(Resource, 9,"CHA_%c%c%02d", g, t, cgsound&0xff); } // only actors have fxqueue's and also the parent function checks for that Actor *caster = (Actor *) fxqueue->GetOwner(); caster->casting_sound = core->GetAudioDrv()->Play(Resource, caster->Pos.x, caster->Pos.y); } fx = EffectQueue::CreateEffect(fx_casting_glow_ref, 0, CastingGraphics, FX_DURATION_ABSOLUTE); fx->Duration = core->GetGame()->GameTime + duration; fx->InventorySlot = 0xffff; fx->Projectile = 0; fxqueue->AddEffect(fx); //AddEffect creates a copy, we need to destroy the original delete fx; }
static inline void GetElements(const char *s, ieVariable *storage, int count) { while(count--) { ieVariable *field = storage+count; strnuprcpy(*field, s, sizeof(ieVariable)-1); for(size_t i=0;i<sizeof(ieVariable) && (*field)[i];i++) { if ((*field)[i]==',') { (*field)[i]='\0'; break; } } while(*s && *s!=',') s++; s++; } }
static inline void GetElements(const char *s, ieResRef *storage, int count) { while(count--) { ieResRef *field = storage+count; strnuprcpy(*field, s, sizeof(ieResRef)-1); for(size_t i=0;i<sizeof(ieResRef) && (*field)[i];i++) { if ((*field)[i]==',') { (*field)[i]='\0'; break; } } if (!count) break; while(*s && *s!=',') s++; s++; if (*s==' ') s++; //this is because there is one single screwed up entry in ar1100.ini } }
void IniSpawn::InitSpawn(const ieResRef DefaultArea) { const char *s; Holder<DataFileMgr> inifile = GetIniFile(DefaultArea); if (!inifile) { strnuprcpy(NamelessSpawnArea, DefaultArea, 8); return; } s = inifile->GetKeyAsString("nameless","destare",DefaultArea); strnuprcpy(NamelessSpawnArea, s, 8); s = inifile->GetKeyAsString("nameless","point","[0.0]"); int x,y; if (sscanf(s,"[%d.%d]", &x, &y)!=2) { x=0; y=0; } NamelessSpawnPoint.x=x; NamelessSpawnPoint.y=y; s = inifile->GetKeyAsString("nameless", "partyarea", DefaultArea); strnuprcpy(PartySpawnArea, s, 8); s = inifile->GetKeyAsString("nameless", "partypoint", "[0.0]"); if (sscanf(s,"[%d.%d]", &x, &y) != 2) { x = NamelessSpawnPoint.x; y = NamelessSpawnPoint.y; } PartySpawnPoint.x = x; PartySpawnPoint.y = y; //35 - already standing //36 - getting up NamelessState = inifile->GetKeyAsInt("nameless","state",36); namelessvarcount = inifile->GetKeysCount("namelessvar"); if (namelessvarcount) { NamelessVar = new VariableSpec[namelessvarcount]; for (y=0;y<namelessvarcount;y++) { const char* Key = inifile->GetKeyNameByIndex("namelessvar",y); strnlwrcpy(NamelessVar[y].Name, Key, 32); NamelessVar[y].Value = inifile->GetKeyAsInt("namelessvar",Key,0); } } localscount = inifile->GetKeysCount("locals"); if (localscount) { Locals = new VariableSpec[localscount]; for (y=0;y<localscount;y++) { const char* Key = inifile->GetKeyNameByIndex("locals",y); strnlwrcpy(Locals[y].Name, Key, 32); Locals[y].Value = inifile->GetKeyAsInt("locals",Key,0); } } s = inifile->GetKeyAsString("spawn_main","enter",NULL); if (s) { ReadSpawnEntry(inifile.get(), s, enterspawn); } s = inifile->GetKeyAsString("spawn_main","exit",NULL); if (s) { ReadSpawnEntry(inifile.get(), s, exitspawn); } s = inifile->GetKeyAsString("spawn_main","events",NULL); if (s) { eventcount = CountElements(s,','); eventspawns = new SpawnEntry[eventcount]; ieVariable *events = new ieVariable[eventcount]; GetElements(s, events, eventcount); int ec = eventcount; while(ec--) { ReadSpawnEntry(inifile.get(), events[ec], eventspawns[ec]); } delete[] events; } //maybe not correct InitialSpawn(); }
/* set by action */ void IniSpawn::SetNamelessDeath(const ieResRef area, Point &pos, ieDword state) { strnuprcpy(NamelessSpawnArea, area, 8); NamelessSpawnPoint = pos; NamelessState = state; }
//unimplemented tags (* marks partially implemented, # marks not working in original either): //*check_crowd // control_var // spec_area //*death_faction //*death_team // check_by_view_port //*do_not_spawn // hold_selected_point_key // inc_spawn_point_index //*find_safest_point //#spawn_time_of_day // exit - similar to enter[spawn], this is a spawn branch type (on exiting an area?) // PST only //*auto_buddy //*detail_level void IniSpawn::ReadCreature(DataFileMgr *inifile, const char *crittername, CritterEntry &critter) const { const char *s; int ps; memset(&critter,0,sizeof(critter)); //first assume it is a simple numeric value critter.TimeOfDay = (ieDword) inifile->GetKeyAsInt(crittername,"time_of_day", 0xffffffff); //at this point critter.TimeOfDay is usually 0xffffffff s = inifile->GetKeyAsString(crittername,"time_of_day",NULL); if (s && strlen(s)>=24) { ieDword value = 0; ieDword j = 1; for(int i=0;i<24 && s[i];i++) { if (s[i]=='0' || s[i]=='o') value |= j; j<<=1; } //turn off individual bits marked by a 24 long string scheduling //example: '0000xxxxxxxxxxxxxxxx00000000' critter.TimeOfDay^=value; } if (inifile->GetKeyAsBool(crittername,"do_not_spawn",false)) { //if the do not spawn flag is true, ignore this entry return; } s = inifile->GetKeyAsString(crittername,"detail_level",NULL); if (s) { ieDword level; switch(s[0]) { case 'h': case 'H': level = 2; break; case 'm': case 'M': level = 1; break; default: level = 0; break; } //If the detail level is lower than this creature's detail level, //skip this entry, creature_count is 0, so it will be ignored at evaluation of the spawn if (level>detail_level) { return; } } //all specvars are using global, but sometimes it is explicitly given s = inifile->GetKeyAsString(crittername,"spec_var",NULL); if (s) { if ((strlen(s)>9) && s[6]==':' && s[7]==':') { strnuprcpy(critter.SpecContext, s, 6); strnlwrcpy(critter.SpecVar, s+8, 32); } else { strnuprcpy(critter.SpecContext, "GLOBAL", 6); strnlwrcpy(critter.SpecVar, s, 32); } } //add this to specvar at each spawn ps = inifile->GetKeyAsInt(crittername,"spec_var_inc", 0); critter.SpecVarInc=ps; //use this value with spec_var_operation to determine spawn ps = inifile->GetKeyAsInt(crittername,"spec_var_value",0); critter.SpecVarValue=ps; //this operation uses DiffCore s = inifile->GetKeyAsString(crittername,"spec_var_operation",""); critter.SpecVarOperator=GetDiffMode(s); //the amount of critters to spawn critter.TotalQuantity = inifile->GetKeyAsInt(crittername,"spec_qty",1); critter.SpawnCount = inifile->GetKeyAsInt(crittername,"create_qty",critter.TotalQuantity); //the creature resource(s) s = inifile->GetKeyAsString(crittername,"cre_file",NULL); if (s) { critter.creaturecount = CountElements(s,','); critter.CreFile=new ieResRef[critter.creaturecount]; GetElements(s, critter.CreFile, critter.creaturecount); } else { Log(ERROR, "IniSpawn", "Invalid spawn entry: %s", crittername); } s = inifile->GetKeyAsString(crittername,"point_select",NULL); if (s) { ps=s[0]; } else { ps=0; } s = inifile->GetKeyAsString(crittername,"spawn_point",NULL); if (s) { //expect more than one spawnpoint if (ps=='r') { //select one of the spawnpoints randomly int count = core->Roll(1,CountElements(s,']'),-1); //go to the selected spawnpoint while(count--) { while(*s++!=']') ; } } //parse the selected spawnpoint int x,y,o; if (sscanf(s,"[%d,%d:%d]", &x, &y, &o)==3) { critter.SpawnPoint.x=(short) x; critter.SpawnPoint.y=(short) y; critter.Orientation=o; } else if (sscanf(s,"[%d.%d:%d]", &x, &y, &o)==3) { critter.SpawnPoint.x=(short) x; critter.SpawnPoint.y=(short) y; critter.Orientation=o; } else if (sscanf(s,"[%d,%d]", &x, &y)==2) { critter.SpawnPoint.x=(short) x; critter.SpawnPoint.y=(short) y; critter.Orientation=core->Roll(1,16,-1); } else if (sscanf(s,"[%d.%d]", &x, &y)==2) { critter.SpawnPoint.x=(short) x; critter.SpawnPoint.y=(short) y; critter.Orientation=core->Roll(1,16,-1); } } //store or retrieve spawn point s = inifile->GetKeyAsString(crittername,"spawn_point_global", NULL); if (s) { switch (ps) { case 'e': critter.SpawnPoint.fromDword(CheckVariable(map, s+8,s)); break; default: //see save_selected_point //SetVariable(map, s+8, s, critter.SpawnPoint.asDword()); break; } } //take facing from variable s = inifile->GetKeyAsString(crittername,"spawn_facing_global", NULL); if (s) { switch (ps) { case 'e': critter.Orientation=(int) CheckVariable(map, s+8,s); break; default: //see save_selected_point //SetVariable(map, s+8, s, (ieDword) critter.Orientation); break; } } s = inifile->GetKeyAsString(crittername,"save_selected_point",NULL); if (s) { if ((strlen(s)>9) && s[6]==':' && s[7]==':') { SetVariable(map, s+8, s, critter.SpawnPoint.asDword()); } else { SetVariable(map, s, "GLOBAL", critter.SpawnPoint.asDword()); } } s = inifile->GetKeyAsString(crittername,"save_selected_facing",NULL); if (s) { if ((strlen(s)>9) && s[6]==':' && s[7]==':') { SetVariable(map, s+8, s, (ieDword) critter.Orientation); } else { SetVariable(map, s, "GLOBAL", (ieDword) critter.Orientation); } } //sometimes only the orientation is given, the point is stored in a variable ps = inifile->GetKeyAsInt(crittername,"facing",-1); if (ps!=-1) critter.Orientation = ps; ps = inifile->GetKeyAsInt(crittername, "ai_ea",-1); if (ps!=-1) critter.SetSpec[AI_EA] = (ieByte) ps; ps = inifile->GetKeyAsInt(crittername, "ai_team",-1); if (ps!=-1) critter.SetSpec[AI_TEAM] = (ieByte) ps; ps = inifile->GetKeyAsInt(crittername, "ai_general",-1); if (ps!=-1) critter.SetSpec[AI_GENERAL] = (ieByte) ps; ps = inifile->GetKeyAsInt(crittername, "ai_race",-1); if (ps!=-1) critter.SetSpec[AI_RACE] = (ieByte) ps; ps = inifile->GetKeyAsInt(crittername, "ai_class",-1); if (ps!=-1) critter.SetSpec[AI_CLASS] = (ieByte) ps; ps = inifile->GetKeyAsInt(crittername, "ai_specifics",-1); if (ps!=-1) critter.SetSpec[AI_SPECIFICS] = (ieByte) ps; ps = inifile->GetKeyAsInt(crittername, "ai_gender",-1); if (ps!=-1) critter.SetSpec[AI_GENDER] = (ieByte) ps; ps = inifile->GetKeyAsInt(crittername, "ai_alignment",-1); if (ps!=-1) critter.SetSpec[AI_ALIGNMENT] = (ieByte) ps; s = inifile->GetKeyAsString(crittername,"spec",NULL); if (s) { int x[9]; ps = sscanf(s,"[%d.%d.%d.%d.%d.%d.%d.%d.%d]", x, x+1, x+2, x+3, x+4, x+5, x+6, x+7, x+8); if (ps == 0) { strnuprcpy(critter.ScriptName, s, 32); critter.Flags|=CF_CHECK_NAME; memset(critter.Spec,-1,sizeof(critter.Spec)); } else { while(ps--) { critter.Spec[ps]=(ieByte) x[ps]; } } } s = inifile->GetKeyAsString(crittername,"script_name",NULL); if (s) { strnuprcpy(critter.ScriptName, s, 32); } //iwd2 script names (override remains the same) //special 1 == area s = inifile->GetKeyAsString(crittername,"script_special_1",NULL); if (s) { strnuprcpy(critter.AreaScript,s, 8); } //special 2 == class s = inifile->GetKeyAsString(crittername,"script_special_2",NULL); if (s) { strnuprcpy(critter.ClassScript,s, 8); } //special 3 == general s = inifile->GetKeyAsString(crittername,"script_special_3",NULL); if (s) { strnuprcpy(critter.GeneralScript,s, 8); } //team == specific s = inifile->GetKeyAsString(crittername,"script_team",NULL); if (s) { strnuprcpy(critter.SpecificScript,s, 8); } //combat == race s = inifile->GetKeyAsString(crittername,"script_combat",NULL); if (s) { strnuprcpy(critter.RaceScript,s, 8); } //movement == default s = inifile->GetKeyAsString(crittername,"script_movement",NULL); if (s) { strnuprcpy(critter.DefaultScript,s, 8); } //pst script names s = inifile->GetKeyAsString(crittername,"script_override",NULL); if (s) { strnuprcpy(critter.OverrideScript,s, 8); } s = inifile->GetKeyAsString(crittername,"script_class",NULL); if (s) { strnuprcpy(critter.ClassScript,s, 8); } s = inifile->GetKeyAsString(crittername,"script_race",NULL); if (s) { strnuprcpy(critter.RaceScript,s, 8); } s = inifile->GetKeyAsString(crittername,"script_general",NULL); if (s) { strnuprcpy(critter.GeneralScript,s, 8); } s = inifile->GetKeyAsString(crittername,"script_default",NULL); if (s) { strnuprcpy(critter.DefaultScript,s, 8); } s = inifile->GetKeyAsString(crittername,"script_area",NULL); if (s) { strnuprcpy(critter.AreaScript,s, 8); } s = inifile->GetKeyAsString(crittername,"script_specifics",NULL); if (s) { strnuprcpy(critter.SpecificScript,s, 8); } s = inifile->GetKeyAsString(crittername,"dialog",NULL); if (s) { strnuprcpy(critter.Dialog,s, 8); } //flags if (inifile->GetKeyAsBool(crittername,"death_scriptname",false)) { critter.Flags|=CF_DEATHVAR; } if (inifile->GetKeyAsBool(crittername,"death_faction",false)) { critter.Flags|=CF_FACTION; } if (inifile->GetKeyAsBool(crittername,"death_team",false)) { critter.Flags|=CF_TEAM; } ps = inifile->GetKeyAsInt(crittername,"good_mod",0); if (ps) { critter.Flags|=CF_GOOD; critter.DeathCounters[DC_GOOD] = ps; } ps = inifile->GetKeyAsInt(crittername,"law_mod",0); if (ps) { critter.Flags|=CF_LAW; critter.DeathCounters[DC_LAW] = ps; } ps = inifile->GetKeyAsInt(crittername,"lady_mod",0); if (ps) { critter.Flags|=CF_LADY; critter.DeathCounters[DC_LADY] = ps; } ps = inifile->GetKeyAsInt(crittername,"murder_mod",0); if (ps) { critter.Flags|=CF_MURDER; critter.DeathCounters[DC_MURDER] = ps; } if(inifile->GetKeyAsBool(crittername,"auto_buddy", false)) { critter.Flags|=CF_BUDDY; } //don't spawn when spawnpoint is visible if (inifile->GetKeyAsBool(crittername,"ignore_can_see",false)) { critter.Flags|=CF_IGNORECANSEE; } //unsure, but could be similar to previous if (inifile->GetKeyAsBool(crittername,"check_view_port", false)) { critter.Flags|=CF_CHECKVIEWPORT; } //unknown, this is used only in pst if (inifile->GetKeyAsBool(crittername,"check_crowd", false)) { critter.Flags|=CF_CHECKCROWD; } //unknown, this is used only in pst if (inifile->GetKeyAsBool(crittername,"find_safest_point", false)) { critter.Flags|=CF_SAFESTPOINT; } //disable spawn based on game difficulty if (inifile->GetKeyAsBool(crittername,"area_diff_1", false)) { critter.Flags|=CF_NO_DIFF_1; } if (inifile->GetKeyAsBool(crittername,"area_diff_2", false)) { critter.Flags|=CF_NO_DIFF_2; } if (inifile->GetKeyAsBool(crittername,"area_diff_3", false)) { critter.Flags|=CF_NO_DIFF_3; } }
Game::Game(void) : Scriptable( ST_GLOBAL ) { protagonist = PM_YES; //set it to 2 for iwd/iwd2 and 0 for pst partysize = 6; Ticks = 0; version = 0; Expansion = 0; LoadMos[0] = 0; TextScreen[0] = 0; SelectedSingle = 1; //the PC we are looking at (inventory, shop) PartyGold = 0; SetScript( core->GlobalScript, 0 ); MapIndex = -1; Reputation = 0; ControlStatus = 0; CombatCounter = 0; //stored here until we know better StateOverrideTime = 0; StateOverrideFlag = 0; BanterBlockTime = 0; BanterBlockFlag = 0; WeatherBits = 0; crtable = NULL; kaputz = NULL; beasts = NULL; mazedata = NULL; timestop_owner = NULL; timestop_end = 0; event_timer = 0; event_handler = NULL; weather = new Particles(200); weather->SetRegion(0, 0, core->Width, core->Height); LastScriptUpdate = 0; //loading master areas AutoTable table; if (table.load("mastarea")) { int i = table->GetRowCount(); mastarea.reserve(i); while(i--) { char *tmp = (char *) malloc(9); strnuprcpy (tmp,table->QueryField(i,0),8); mastarea.push_back( tmp ); } } //loading rest/daylight switching movies (only bg2 has them) memset(restmovies,'*',sizeof(restmovies)); memset(daymovies,'*',sizeof(daymovies)); memset(nightmovies,'*',sizeof(nightmovies)); if (table.load("restmov")) { for(int i=0;i<8;i++) { strnuprcpy(restmovies[i],table->QueryField(i,0),8); strnuprcpy(daymovies[i],table->QueryField(i,1),8); strnuprcpy(nightmovies[i],table->QueryField(i,2),8); } } //loading npc starting levels ieResRef tn; if (Expansion == 5) { // tob is special CopyResRef(tn, "npclvl25"); } else { CopyResRef(tn, "npclevel"); } if (table.load(tn)) { int cols = table->GetColumnCount(); int rows = table->GetRowCount(); int i, j; npclevels.reserve(rows); for (i = 0; i < rows; i++) { npclevels.push_back (std::vector<char *>(cols+1)); for(j = -1; j < cols; j++) { char *ref = new char[9]; if (j == -1) { CopyResRef(ref, table->GetRowName(i)); npclevels[i][j+1] = ref; } else { CopyResRef(ref, table->QueryField(i, j)); npclevels[i][j+1] = ref; } } } } interval = 1000/AI_UPDATE_TIME; hasInfra = false; familiarBlock = false; //FIXME:i'm not sure in this... NoInterrupt(); bntchnc = NULL; bntrows = -1; }
void InfoPoint::SetEnter(const char *resref) { if (gamedata->Exists(resref, IE_WAV_CLASS_ID) ) { strnuprcpy(EnterWav, resref, 8); } }
Game::Game(void) : Scriptable( ST_GLOBAL ) { protagonist = PM_YES; //set it to 2 for iwd/iwd2 and 0 for pst partysize = 6; Ticks = 0; version = 0; Expansion = 0; LoadMos[0] = 0; SelectedSingle = 1; //the PC we are looking at (inventory, shop) PartyGold = 0; SetScript( core->GlobalScript, 0 ); MapIndex = -1; Reputation = 0; ControlStatus = 0; CombatCounter = 0; //stored here until we know better StateOverrideTime = 0; StateOverrideFlag = 0; BanterBlockTime = 0; BanterBlockFlag = 0; WeatherBits = 0; crtable = NULL; kaputz = NULL; beasts = NULL; mazedata = NULL; timestop_owner = NULL; timestop_end = 0; event_timer = 0; event_handler = NULL; weather = new Particles(200); weather->SetRegion(0, 0, core->Width, core->Height); LastScriptUpdate = 0; //loading master areas AutoTable table; if (table.load("mastarea")) { int i = table->GetRowCount(); mastarea.reserve(i); while(i--) { char *tmp = (char *) malloc(9); strnuprcpy (tmp,table->QueryField(i,0),8); mastarea.push_back( tmp ); } } //loading rest/daylight switching movies (only bg2 has them) memset(restmovies,'*',sizeof(restmovies)); memset(daymovies,'*',sizeof(restmovies)); memset(nightmovies,'*',sizeof(restmovies)); if (table.load("restmov")) { for(int i=0;i<8;i++) { strnuprcpy(restmovies[i],table->QueryField(i,0),8); strnuprcpy(daymovies[i],table->QueryField(i,1),8); strnuprcpy(nightmovies[i],table->QueryField(i,2),8); } } interval = 1000/AI_UPDATE_TIME; hasInfra = false; familiarBlock = false; //FIXME:i'm not sure in this... NoInterrupt(); }