Implementation wise, it's basically a hashmap of screens pointing to a linked list of "scorched" locations, all stuffed into a single array. It could probably be rather easily modified to keep track of "permanent" combo changes for other reasons, as well.
So, any suggestions/recommendations before I bundle it up for the database?
Test quest here.
Pictures:
Obviously, for your quest you'll want less of a drastic change here.
This is the most difficult part of the setup here:
int Scorch_Combos[] = { LW_BOMBBLAST, 25, 33, LW_FIRE, 92, 80 };Basically, just a list of weapon type, from combo, and to combo.
Code:
Spoiler
////////////////////////////////////////////////////////////////// Scorch // by grayswandir //////////////////////////////////////////////////////////////// // Permanently mark walls and bushes that you've bombed/burned, but didn't // actually have a secret. //////////////////////////////////////////////////////////////// // Setup: // Put Scorch_Update() in your active loop. // // Mess with the configuration section. Particularly, you'll need to list all // the combo ids and what they change into. (Don't chain combo ids, I don't // think it'll work.)//////////////////////////////////////////////////////////////// // Configuration.// This is whether scorching is enabled or disabled by default. 1 for enabled, // 0 for disabled. const int SCORCH_DEFAULT = 1;// This is the screen script flag number used to toggle a screen being able to // be scorched. From 1 to 5. Anything else ignores. const int SCORCH_TOGGLE_SCREEN_FLAG = 1;// This is the dmap script flag number used to toggle scorching on a // dmap. From 1 to 5. Anything else ignores. const int SCORCH_TOGGLE_DMAP_FLAG = 1;// This is the maximum number of screens that can be scorched. Make it as // small as you can. const int SCORCH_MAX_SCREENS = 5000;// This is the array of combo ids for scorching. They alternate between the // weapon used to scorch, the original combo id, and the scorch combo id that // it is changed to. int Scorch_Combos[] = { LW_BOMBBLAST, 25, 33, LW_FIRE, 92, 80 };//////////////////////////////////////////////////////////////// // Code// The actual data of which combos are scorched. int Scorch_Data[200000];const int SCORCH_DATA_INIT = 0; const int SCORCH_DATA_ENABLED = 1; const int SCORCH_DATA_LAST_SCREEN = 2; const int SCORCH_DATA_NEXT_INDEX = 3; const int SCORCH_DATA_SCREEN_START = 4;// Get the screen index in the scorch data. -1 for out of screens. int Scorch_GetScreenIndex() { int screen = (Game->GetCurMap() << 8) + Game->GetCurScreen(); int index = screen % SCORCH_MAX_SCREENS; int data = Scorch_Data[SCORCH_DATA_SCREEN_START + 2 * index]; while (data != 0 && data != screen) { index = (index + 1) % SCORCH_MAX_SCREENS; data = Scorch_Data[SCORCH_DATA_SCREEN_START + 2 * index]; // If we've wrapped completely around, that means we're out of screens. if (index == screen % SCORCH_MAX_SCREENS) {return -1;} } return 2 * index + SCORCH_DATA_SCREEN_START; }// Scorch the specified combo location. void Scorch_Location(int weapon_id, int location) { int combo; int index; int target_combo;// First, check to see if it matches a pre-scorch combo. combo = Screen->ComboD[location]; target_combo = -1; for (index = 0; index < SizeOfArray(Scorch_Combos); index += 3) { if (Scorch_Combos[index] == weapon_id && Scorch_Combos[index + 1] == combo) { target_combo = Scorch_Combos[index + 2]; break; } }// If there's no match, exit. if (-1 == target_combo) {return;}// Alter the actual combo. Screen->ComboD[location] = target_combo;// Now, find this screen in the scorch data. index = Scorch_GetScreenIndex();// If we don't have the screen marked, Enter the scorch as the first entry. if (!Scorch_Data[index]) { Scorch_Data[index] = (Game->GetCurMap() << 8) + Game->GetCurScreen(); Scorch_Data[index + 1] = Scorch_Data[SCORCH_DATA_NEXT_INDEX]; index = Scorch_Data[SCORCH_DATA_NEXT_INDEX]; Scorch_Data[index] = location; Scorch_Data[SCORCH_DATA_NEXT_INDEX] += 2; return; }// If we do have the screen marked, we first need to advance to the first // open position for this screen. while (Scorch_Data[index + 1]) {index = Scorch_Data[index + 1];}// Then create the entry. Scorch_Data[index + 1] = Scorch_Data[SCORCH_DATA_NEXT_INDEX]; index = Scorch_Data[SCORCH_DATA_NEXT_INDEX]; Scorch_Data[index] = location; Scorch_Data[SCORCH_DATA_NEXT_INDEX] += 2; }void Scorch_Update() { int screen; int start_index; int index; int data; int location; int combo; int combo_index;if (!Scorch_Data[SCORCH_DATA_INIT]) { Scorch_Data[SCORCH_DATA_INIT] = 1; Scorch_Data[SCORCH_DATA_ENABLED] = 0; Scorch_Data[SCORCH_DATA_LAST_SCREEN] = -1; Scorch_Data[SCORCH_DATA_NEXT_INDEX] = SCORCH_DATA_SCREEN_START + SCORCH_MAX_SCREENS; }screen = (Game->GetCurMap() << 8) + Game->GetCurScreen();// Check to see if we've changed screens and need to change out the combos. if (screen != Scorch_Data[SCORCH_DATA_LAST_SCREEN]) { // Remember the screen. Scorch_Data[SCORCH_DATA_LAST_SCREEN] = screen; // Check to see if this screen is enabled. Scorch_Data[SCORCH_DATA_ENABLED] = SCORCH_DEFAULT; Trace(Scorch_Data[SCORCH_DATA_ENABLED]); if (1 <= SCORCH_TOGGLE_SCREEN_FLAG && SCORCH_TOGGLE_SCREEN_FLAG <= 5) { if (Screen->Flags[SF_MISC] & (2 << SCORCH_TOGGLE_SCREEN_FLAG)) { Scorch_Data[SCORCH_DATA_ENABLED] = Cond(!Scorch_Data[SCORCH_DATA_ENABLED], 1, 0); Trace(Scorch_Data[SCORCH_DATA_ENABLED]); } } if (1 <= SCORCH_TOGGLE_DMAP_FLAG && SCORCH_TOGGLE_DMAP_FLAG <= 5) { if (Game->DMapFlags[Game->GetCurDMap()] & (DMF_SCRIPT1 << (SCORCH_TOGGLE_DMAP_FLAG - 1))) { Scorch_Data[SCORCH_DATA_ENABLED] = Cond(!Scorch_Data[SCORCH_DATA_ENABLED], 1, 0); Trace(Scorch_Data[SCORCH_DATA_ENABLED]); } } // Find the screen in the screen list, or an empty space. index = Scorch_GetScreenIndex(); // Out of screens. if (-1 == index) {return;} // Screen not found. if (0 == Scorch_Data[index]) {return;} // If we have data for this screen, replace all the marked combos. index = Scorch_Data[index + 1]; while (index) { location = Scorch_Data[index]; combo = Screen->ComboD[location]; // Look through the combo list for this combo. combo_index = 1; while (Scorch_Combos[combo_index] != combo && combo_index < SizeOfArray(Scorch_Combos)) { combo_index += 3; } // If we found the combo, replace it. if (Scorch_Combos[combo_index] == combo) { Screen->ComboD[location] = Scorch_Combos[combo_index + 1]; } // Advance to the next saved location. index = Scorch_Data[index + 1]; } }if (!Scorch_Data[SCORCH_DATA_ENABLED]) {return;}// Check for an explosion. for (index = 1; index <= Screen->NumLWeapons(); ++index) { lweapon weapon = Screen->LoadLWeapon(index); if (LW_BOMBBLAST == weapon->ID) { Scorch_Location(LW_BOMBBLAST, ComboAt(weapon->X, weapon->Y)); Scorch_Location(LW_BOMBBLAST, ComboAt(weapon->X + 16, weapon->Y)); Scorch_Location(LW_BOMBBLAST, ComboAt(weapon->X, weapon->Y + 16)); Scorch_Location(LW_BOMBBLAST, ComboAt(weapon->X + 16, weapon->Y + 16)); } if (LW_FIRE == weapon->ID) { Scorch_Location(LW_FIRE, ComboAt(weapon->X + 8, weapon->Y + 8)); } }}
Edited by grayswandir, 19 April 2016 - 06:50 PM.