int ExecutingScript::queue_action(PostScriptAction act, int data, const char *aname) { if (numPostScriptActions >= MAX_QUEUED_ACTIONS) quitprintf("!%s: Cannot queue action, post-script queue full", aname); if (numPostScriptActions > 0) { // if something that will terminate the room has already // been queued, don't allow a second thing to be queued switch (postScriptActions[numPostScriptActions - 1]) { case ePSANewRoom: case ePSARestoreGame: case ePSARestoreGameDialog: case ePSARunAGSGame: case ePSARestartGame: quitprintf("!%s: Cannot run this command, since there was a %s command already queued to run in \"%s\", line %d", aname, postScriptActionNames[numPostScriptActions - 1], postScriptActionPositions[numPostScriptActions - 1].Section.GetCStr(), postScriptActionPositions[numPostScriptActions - 1].Line); break; // MACPORT FIX 9/6/5: added default clause to remove warning default: break; } } postScriptActions[numPostScriptActions] = act; postScriptActionData[numPostScriptActions] = data; postScriptActionNames[numPostScriptActions] = aname; get_script_position(postScriptActionPositions[numPostScriptActions]); numPostScriptActions++; return numPostScriptActions - 1; }
void NewRoom(int nrnum) { if (nrnum < 0) quitprintf("!NewRoom: room change requested to invalid room number %d.", nrnum); if (displayed_room < 0) { // called from game_start; change the room where the game will start playerchar->room = nrnum; return; } DEBUG_CONSOLE("Room change requested to room %d", nrnum); EndSkippingUntilCharStops(); can_run_delayed_command(); if (play.stop_dialog_at_end != DIALOG_NONE) { if (play.stop_dialog_at_end == DIALOG_RUNNING) play.stop_dialog_at_end = DIALOG_NEWROOM + nrnum; else { quitprintf("!NewRoom: two NewRoom/RunDialog/StopDialog requests within dialog; last was called in \"%s\", line %d", last_in_dialog_request_script_pos.Section.GetCStr(), last_in_dialog_request_script_pos.Line); } return; } get_script_position(last_in_dialog_request_script_pos); if (in_leaves_screen >= 0) { // NewRoom called from the Player Leaves Screen event -- just // change which room it will go to in_leaves_screen = nrnum; } else if (in_enters_screen) { setevent(EV_NEWROOM,nrnum); return; } else if (in_inv_screen) { inv_screen_newroom = nrnum; return; } else if ((inside_script==0) & (in_graph_script==0)) { new_room(nrnum,playerchar); return; } else if (inside_script) { curscript->queue_action(ePSANewRoom, nrnum, "NewRoom"); // we might be within a MoveCharacterBlocking -- the room // change should abort it if ((playerchar->walking > 0) && (playerchar->walking < TURNING_AROUND)) { // nasty hack - make sure it doesn't move the character // to a walkable area mls[playerchar->walking].direct = 1; StopMoving(game.playercharacter); } } else if (in_graph_script) gs_to_newroom = nrnum; }
int RunTextScript(ccInstance *sci, const char *tsname) { if (strcmp(tsname, REP_EXEC_NAME) == 0) { // run module rep_execs // FIXME: in theory the function may be already called for moduleInst[i], // in which case this should not be executed; need to rearrange the code somehow int room_changes_was = play.room_changes; int restore_game_count_was = gameHasBeenRestored; for (int kk = 0; kk < numScriptModules; kk++) { if (!moduleRepExecAddr[kk].IsNull()) RunScriptFunctionIfExists(moduleInst[kk], tsname, 0, nullptr); if ((room_changes_was != play.room_changes) || (restore_game_count_was != gameHasBeenRestored)) return 0; } } int toret = RunScriptFunctionIfExists(sci, tsname, 0, nullptr); if ((toret == -18) && (sci == roominst)) { // functions in room script must exist quitprintf("prepare_script: error %d (%s) trying to run '%s' (Room %d)", toret, ccErrorString.GetCStr(), tsname, displayed_room); } return toret; }
void DisplayAtY (int ypos, char *texx) { if ((ypos < -1) || (ypos >= GetMaxScreenHeight())) quitprintf("!DisplayAtY: invalid Y co-ordinate supplied (used: %d; valid: 0..%d)", ypos, GetMaxScreenHeight()); // Display("") ... a bit of a stupid thing to do, so ignore it if (texx[0] == 0) return; if (ypos > 0) ypos = multiply_up_coordinate(ypos); if (game.options[OPT_ALWAYSSPCH]) DisplaySpeechAt(-1, (ypos > 0) ? divide_down_coordinate(ypos) : ypos, -1, game.playercharacter, texx); else { // Normal "Display" in text box if (screen_is_dirty) { // erase any previous DisplaySpeech play.disabled_user_interface ++; mainloop(); play.disabled_user_interface --; } _display_at(-1,ypos,scrnwid/2+scrnwid/4,get_translation(texx),1,0, 0, 0, false); } }
void SetMusicMasterVolume(int newvol) { const int min_volume = loaded_game_file_version < kGameVersion_330 ? 0 : -LegacyMusicMasterVolumeAdjustment - (kRoomVolumeMax * LegacyRoomVolumeFactor); if ((newvol < min_volume) | (newvol>100)) quitprintf("!SetMusicMasterVolume: invalid volume - must be from %d to %d", min_volume, 100); play.music_master_volume=newvol+LegacyMusicMasterVolumeAdjustment; update_music_volume(); }
// [DEPRECATED] still used by Character_SetAsPlayer void SetActiveInventory(int iit) { ScriptInvItem *tosend = NULL; if ((iit > 0) && (iit < game.numinvitems)) tosend = &scrInv[iit]; else if (iit != -1) quitprintf("!SetActiveInventory: invalid inventory number %d", iit); Character_SetActiveInventory(playerchar, tosend); }
void System_SetGamma(int newValue) { if ((newValue < 0) || (newValue > 200)) quitprintf("!System.Gamma: value must be between 0-200 (not %d)", newValue); if (play.gamma_adjustment != newValue) { DEBUG_CONSOLE("Gamma control set to %d", newValue); play.gamma_adjustment = newValue; if (gfxDriver->SupportsGammaControl()) gfxDriver->SetGamma(newValue); } }
int RunScriptFunctionIfExists(ccInstance *sci, const char*tsname, int numParam, const RuntimeScriptValue *params) { int oldRestoreCount = gameHasBeenRestored; // First, save the current ccError state // This is necessary because we might be attempting // to run Script B, while Script A is still running in the // background. // If CallInstance here has an error, it would otherwise // also abort Script A because ccError is a global variable. int cachedCcError = ccError; ccError = 0; int toret = PrepareTextScript(sci, &tsname); if (toret) { ccError = cachedCcError; return -18; } // Clear the error message ccErrorString = ""; if (numParam < 3) { toret = curscript->inst->CallScriptFunction(tsname, numParam, params); } else quit("Too many parameters to RunScriptFunctionIfExists"); // 100 is if Aborted (eg. because we are LoadAGSGame'ing) if ((toret != 0) && (toret != -2) && (toret != 100)) { quit_with_script_error(tsname); } post_script_cleanup_stack++; if (post_script_cleanup_stack > 50) quitprintf("!post_script_cleanup call stack exceeded: possible recursive function call? running %s", tsname); post_script_cleanup(); post_script_cleanup_stack--; // restore cached error state ccError = cachedCcError; // if the game has been restored, ensure that any further scripts are not run if ((oldRestoreCount != gameHasBeenRestored) && (eventClaimed == EVENT_INPROGRESS)) eventClaimed = EVENT_CLAIMED; return toret; }
void PlaySilentMIDI (int mnum) { if (current_music_type == MUS_MIDI) quit("!PlaySilentMIDI: proper midi music is in progress"); set_volume (-1, 0); play.silent_midi = mnum; play.silent_midi_channel = SCHAN_SPEECH; stop_and_destroy_channel(play.silent_midi_channel); channels[play.silent_midi_channel] = load_sound_clip_from_old_style_number(true, mnum, false); if (channels[play.silent_midi_channel] == NULL) { quitprintf("!PlaySilentMIDI: failed to load aMusic%d", mnum); } channels[play.silent_midi_channel]->play(); channels[play.silent_midi_channel]->set_volume_percent(0); }
void IAGSEngine::AddManagedObjectReader(const char *typeName, IAGSManagedObjectReader *reader) { if (numPluginReaders >= MAX_PLUGIN_OBJECT_READERS) quit("Plugin error: IAGSEngine::AddObjectReader: Too many object readers added"); if ((typeName == NULL) || (typeName[0] == 0)) quit("Plugin error: IAGSEngine::AddObjectReader: invalid name for type"); for (int ii = 0; ii < numPluginReaders; ii++) { if (strcmp(pluginReaders[ii].type, typeName) == 0) quitprintf("Plugin error: IAGSEngine::AddObjectReader: type '%s' has been registered already", typeName); } pluginReaders[numPluginReaders].reader = reader; pluginReaders[numPluginReaders].type = typeName; numPluginReaders++; }
/* *** SCRIPT SYMBOL: [GUI] GUI::SetSize^2 *** */ void GUI_SetSize(ScriptGUI *sgui, int widd, int hitt) { if ((widd < 1) || (hitt < 1) || (widd > BASEWIDTH) || (hitt > GetMaxScreenHeight())) quitprintf("!SetGUISize: invalid dimensions (tried to set to %d x %d)", widd, hitt); GUIMain *tehgui = sgui->gui; multiply_up_coordinates(&widd, &hitt); if ((tehgui->wid == widd) && (tehgui->hit == hitt)) return; tehgui->wid = widd; tehgui->hit = hitt; recreate_guibg_image(tehgui); guis_need_update = 1; }
void LoadFonts() { for (int i = 0; i < game.numfonts; ++i) { int fontsize = game.fontflags[i] & FFLG_SIZEMASK; if (fontsize == 0) fontsize = 8; if ((game.options[OPT_NOSCALEFNT] == 0) && game.IsHiRes()) fontsize *= 2; FontRenderParams params; params.YOffset = game.fontvoffset[i]; if (!wloadfont_size(i, fontsize, ¶ms)) quitprintf("Unable to load font %d, no renderer could load a matching file", i); } }
void start_game_load_savegame_on_startup() { if (loadSaveGameOnStartup != NULL) { int saveGameNumber = 1000; const char *sgName = strstr(loadSaveGameOnStartup, "agssave."); if (sgName != NULL) { sscanf(sgName, "agssave.%03d", &saveGameNumber); } current_fade_out_effect(); int loadGameErrorCode = load_game(loadSaveGameOnStartup, saveGameNumber); if (loadGameErrorCode) { quitprintf("Unable to resume the save game. Try starting the game over. (Error: %s)", load_game_errors[-loadGameErrorCode]); } } }
void LoadFonts() { for (int i = 0; i < game.numfonts; ++i) { FontInfo finfo = game.fonts[i]; // Apply compatibility adjustments if (finfo.SizePt == 0) finfo.SizePt = 8; // CLNUP decide what to do about arbitrary font scaling, might become an option // TODO: for some reason these compat fixes are different in the editor, investigate /* if ((game.options[OPT_NOSCALEFNT] == 0) && game.IsHiRes()) finfo.SizePt *= 2; */ if (!wloadfont_size(i, finfo, NULL)) quitprintf("Unable to load font %d, no renderer could load a matching file", i); } }
void SetFrameSound (int vii, int loop, int frame, int sound) { if ((vii < 1) || (vii > game.numviews)) quit("!SetFrameSound: invalid view number"); vii--; if (loop >= views[vii].numLoops) quit("!SetFrameSound: invalid loop number"); if (frame >= views[vii].loops[loop].numFrames) quit("!SetFrameSound: invalid frame number"); if (sound < 1) { views[vii].loops[loop].frames[frame].sound = -1; } else { ScriptAudioClip* clip = GetAudioClipForOldStyleNumber(game, false, sound); if (clip == NULL) quitprintf("!SetFrameSound: audio clip aSound%d not found", sound); views[vii].loops[loop].frames[frame].sound = clip->id + (is_old_audio_system() ? 0x10000000 : 0); } }
// Custom printf, needed because floats are pushed as 8 bytes void my_sprintf(char *buffer, const char *fmt, va_list ap) { int bufidx = 0; const char *curptr = fmt; const char *endptr; char spfbuffer[STD_BUFFER_SIZE]; char fmtstring[100]; int numargs = -1; while (1) { // copy across everything until the next % (or end of string) endptr = strchr(curptr, '%'); if (endptr == NULL) endptr = &curptr[strlen(curptr)]; while (curptr < endptr) { buffer[bufidx] = *curptr; curptr++; bufidx++; } // at this point, curptr and endptr should be equal and pointing // to the % or \0 if (*curptr == 0) break; if (curptr[1] == '%') { // "%%", so just write a % to the output buffer[bufidx] = '%'; bufidx++; curptr += 2; continue; } // find the end of the % clause while ((*endptr != 'd') && (*endptr != 'f') && (*endptr != 'c') && (*endptr != 0) && (*endptr != 's') && (*endptr != 'x') && (*endptr != 'X')) endptr++; if (numargs >= 0) { numargs--; // if there are not enough arguments, just copy the %d // to the output string rather than trying to format it if (numargs < 0) endptr = &curptr[strlen(curptr)]; } if (*endptr == 0) { // something like %p which we don't support, so just write // the % to the output buffer[bufidx] = '%'; bufidx++; curptr++; continue; } // move endptr to 1 after the end character endptr++; // copy the %d or whatever strncpy(fmtstring, curptr, (endptr - curptr)); fmtstring[endptr - curptr] = 0; unsigned int theArg = va_arg(ap, unsigned int); // use sprintf to parse the actual %02d type thing if (endptr[-1] == 'f') { // floats are pushed as 8-bytes, so ensure that it knows this is a float float floatArg = *((float*)&theArg); sprintf(spfbuffer, fmtstring, floatArg); } else if ((theArg == (int)buffer) && (endptr[-1] == 's')) quit("Cannot use destination as argument to StrFormat"); else if ((theArg < 0x10000) && (endptr[-1] == 's')) quit("!One of the string arguments supplied was not a string"); else if (endptr[-1] == 's') { strncpy(spfbuffer, (const char*)theArg, STD_BUFFER_SIZE); spfbuffer[STD_BUFFER_SIZE - 1] = 0; } else sprintf(spfbuffer, fmtstring, theArg); // use the formatted text buffer[bufidx] = 0; if (bufidx + strlen(spfbuffer) >= STD_BUFFER_SIZE) quitprintf("!String.Format: buffer overrun: maximum formatted string length %d chars, this string: %d chars", STD_BUFFER_SIZE, bufidx + strlen(spfbuffer)); strcat(buffer, spfbuffer); bufidx += strlen(spfbuffer); curptr = endptr; } buffer[bufidx] = 0; }
PACKFILE *pack_fopen(const char *filnam1, const char *modd1) { #else PACKFILE *pack_fopen(char *filnam1, char *modd1) { #endif char msg[2000]; sprintf(msg, "pack_fopen: %s - %s\n", filnam1, modd1); write_log_debug(msg); char *filnam = (char *)filnam1; char *modd = (char *)modd1; int needsetback = 0; if (filnam[0] == '~') { // ~ signals load from specific data file, not the main default one char gfname[80]; int ii = 0; filnam++; while (filnam[0]!='~') { gfname[ii] = filnam[0]; filnam++; ii++; } filnam++; // MACPORT FIX 9/6/5: changed from NULL TO '\0' gfname[ii] = '\0'; /* char useloc[250]; #ifdef LINUX_VERSION sprintf(useloc,"%s/%s",usetup.data_files_dir,gfname); #else sprintf(useloc,"%s\\%s",usetup.data_files_dir,gfname); #endif csetlib(useloc,"");*/ char *libname = ci_find_file(usetup.data_files_dir, gfname); if (csetlib(libname,"")) { // Hack for running in Debugger free(libname); libname = ci_find_file("Compiled", gfname); csetlib(libname,""); } free(libname); needsetback = 1; } // if the file exists, override the internal file FILE *testf = fopen(filnam, "rb"); if (testf != NULL) fclose(testf); if ((cliboffset(filnam)<1) || (testf != NULL)) { if (needsetback) csetlib(game_file_name,""); return __old_pack_fopen(filnam, modd); } else { _my_temppack=__old_pack_fopen(clibgetdatafile(filnam), modd); if (_my_temppack == NULL) quitprintf("pack_fopen: unable to change datafile: not found: %s", clibgetdatafile(filnam)); pack_fseek(_my_temppack,cliboffset(filnam)); #if ALLEGRO_DATE < 20050101 _my_temppack->todo=clibfilesize(filnam); #else _my_temppack->normal.todo = clibfilesize(filnam); #endif if (needsetback) csetlib(game_file_name,""); return _my_temppack; } }
void quit_with_script_error(const char *functionName) { quitprintf("%sError running function '%s':\n%s", (ccErrorIsUserError ? "!" : ""), functionName, ccErrorString); }
void post_script_cleanup() { // should do any post-script stuff here, like go to new room if (ccError) quit(ccErrorString); ExecutingScript copyof = scripts[num_scripts-1]; // write_log("Instance finished."); if (scripts[num_scripts-1].forked) delete scripts[num_scripts-1].inst; num_scripts--; inside_script--; if (num_scripts > 0) curscript = &scripts[num_scripts-1]; else { curscript = NULL; } // if (abort_executor) user_disabled_data2=aborted_ip; int old_room_number = displayed_room; // run the queued post-script actions for (int ii = 0; ii < copyof.numPostScriptActions; ii++) { int thisData = copyof.postScriptActionData[ii]; switch (copyof.postScriptActions[ii]) { case ePSANewRoom: // only change rooms when all scripts are done if (num_scripts == 0) { new_room(thisData, playerchar); // don't allow any pending room scripts from the old room // in run_another to be executed return; } else curscript->queue_action(ePSANewRoom, thisData, "NewRoom"); break; case ePSAInvScreen: invscreen(); break; case ePSARestoreGame: cancel_all_scripts(); try_restore_save(thisData); return; case ePSARestoreGameDialog: restore_game_dialog(); return; case ePSARunAGSGame: cancel_all_scripts(); load_new_game = thisData; return; case ePSARunDialog: do_conversation(thisData); break; case ePSARestartGame: cancel_all_scripts(); restart_game(); return; case ePSASaveGame: save_game(thisData, copyof.postScriptSaveSlotDescription[ii]); break; case ePSASaveGameDialog: save_game_dialog(); break; default: quitprintf("undefined post script action found: %d", copyof.postScriptActions[ii]); } // if the room changed in a conversation, for example, abort if (old_room_number != displayed_room) { return; } } int jj; for (jj = 0; jj < copyof.numanother; jj++) { old_room_number = displayed_room; QueuedScript &script = copyof.ScFnQueue[jj]; RunScriptFunction(script.Instance, script.FnName, script.ParamCount, script.Param1, script.Param2); if (script.Instance == kScInstRoom && script.ParamCount == 1) { // some bogus hack for "on_call" event handler play.roomscript_finished = 1; } // if they've changed rooms, cancel any further pending scripts if ((displayed_room != old_room_number) || (load_new_game)) break; } copyof.numanother = 0; }
void SetMusicVolume(int newvol) { if ((newvol < kRoomVolumeMin) || (newvol > kRoomVolumeMax)) quitprintf("!SetMusicVolume: invalid volume number. Must be from %d to %d.", kRoomVolumeMin, kRoomVolumeMax); thisroom.options[ST_VOLUME]=newvol; update_music_volume(); }
void CharacterInfo::update_character_moving(int &char_index, CharacterExtras *chex, int &doing_nothing) { if ((walking > 0) && (room == displayed_room)) { if (walkwait > 0) walkwait--; else { flags &= ~CHF_AWAITINGMOVE; // Move the character int numSteps = wantMoveNow(this, chex); if ((numSteps) && (chex->xwas != INVALID_X)) { // if the zoom level changed mid-move, the walkcounter // might not have come round properly - so sort it out x = chex->xwas; y = chex->ywas; chex->xwas = INVALID_X; } int oldxp = x, oldyp = y; for (int ff = 0; ff < abs(numSteps); ff++) { if (doNextCharMoveStep (this, char_index, chex)) break; if ((walking == 0) || (walking >= TURNING_AROUND)) break; } if (numSteps < 0) { // very small scaling, intersperse the movement // to stop it being jumpy chex->xwas = x; chex->ywas = y; x = ((x) - oldxp) / 2 + oldxp; y = ((y) - oldyp) / 2 + oldyp; } else if (numSteps > 0) chex->xwas = INVALID_X; if ((flags & CHF_ANTIGLIDE) == 0) walkwaitcounter++; } if (loop >= views[view].numLoops) quitprintf("Unable to render character %d (%s) because loop %d does not exist in view %d", index_id, name, loop, view + 1); // check don't overflow loop int framesInLoop = views[view].loops[loop].numFrames; if (frame > framesInLoop) { frame = 1; if (framesInLoop < 2) frame = 0; if (framesInLoop < 1) quitprintf("Unable to render character %d (%s) because there are no frames in loop %d", index_id, name, loop); } if (walking<1) { chex->process_idle_this_time = 1; doing_nothing=1; walkwait=0; chex->animwait = 0; // use standing pic Character_StopMoving(this); frame = 0; CheckViewFrameForCharacter(this); } else if (chex->animwait > 0) chex->animwait--; else { if (flags & CHF_ANTIGLIDE) walkwaitcounter++; if ((flags & CHF_MOVENOTWALK) == 0) { frame++; if (frame >= views[view].loops[loop].numFrames) { // end of loop, so loop back round skipping the standing frame frame = 1; if (views[view].loops[loop].numFrames < 2) frame = 0; } chex->animwait = views[view].loops[loop].frames[frame].speed + animspeed; if (flags & CHF_ANTIGLIDE) walkwait = chex->animwait; else walkwait = 0; CheckViewFrameForCharacter(this); } } doing_nothing = 0; } }
void AGSDeSerializer::Unserialize(int index, const char *objectType, const char *serializedData, int dataSize) { if (strcmp(objectType, "GUIObject") == 0) { ccDynamicGUIObject.Unserialize(index, serializedData, dataSize); } else if (strcmp(objectType, "Character") == 0) { ccDynamicCharacter.Unserialize(index, serializedData, dataSize); } else if (strcmp(objectType, "Hotspot") == 0) { ccDynamicHotspot.Unserialize(index, serializedData, dataSize); } else if (strcmp(objectType, "Region") == 0) { ccDynamicRegion.Unserialize(index, serializedData, dataSize); } else if (strcmp(objectType, "Inventory") == 0) { ccDynamicInv.Unserialize(index, serializedData, dataSize); } else if (strcmp(objectType, "Dialog") == 0) { ccDynamicDialog.Unserialize(index, serializedData, dataSize); } else if (strcmp(objectType, "GUI") == 0) { ccDynamicGUI.Unserialize(index, serializedData, dataSize); } else if (strcmp(objectType, "Object") == 0) { ccDynamicObject.Unserialize(index, serializedData, dataSize); } else if (strcmp(objectType, "String") == 0) { ScriptString *scf = new ScriptString(); scf->Unserialize(index, serializedData, dataSize); } else if (strcmp(objectType, "File") == 0) { // files cannot be restored properly -- so just recreate // the object; attempting any operations on it will fail sc_File *scf = new sc_File(); ccRegisterUnserializedObject(index, scf, scf); } else if (strcmp(objectType, "Overlay") == 0) { ScriptOverlay *scf = new ScriptOverlay(); scf->Unserialize(index, serializedData, dataSize); } else if (strcmp(objectType, "DateTime") == 0) { ScriptDateTime *scf = new ScriptDateTime(); scf->Unserialize(index, serializedData, dataSize); } else if (strcmp(objectType, "ViewFrame") == 0) { ScriptViewFrame *scf = new ScriptViewFrame(); scf->Unserialize(index, serializedData, dataSize); } else if (strcmp(objectType, "DynamicSprite") == 0) { ScriptDynamicSprite *scf = new ScriptDynamicSprite(); scf->Unserialize(index, serializedData, dataSize); } else if (strcmp(objectType, "DrawingSurface") == 0) { ScriptDrawingSurface *sds = new ScriptDrawingSurface(); sds->Unserialize(index, serializedData, dataSize); if (sds->isLinkedBitmapOnly) { dialogOptionsRenderingSurface = sds; } } else if (strcmp(objectType, "DialogOptionsRendering") == 0) { ccDialogOptionsRendering.Unserialize(index, serializedData, dataSize); } else if (!unserialize_audio_script_object(index, objectType, serializedData, dataSize)) { // check if the type is read by a plugin for (int ii = 0; ii < numPluginReaders; ii++) { if (strcmp(objectType, pluginReaders[ii].type) == 0) { pluginReaders[ii].reader->Unserialize(index, serializedData, dataSize); return; } } quitprintf("Unserialise: unknown object type: '%s'", objectType); } }