Compare commits

...
Author SHA1 Message Date
Goober5000 19ca467c41 Merge pull request #4513 from EatThePath/cleanup-eval-stack
Clean up the lua stack after EvalStringWithReturn's function creation
2022-07-27 23:29:52 -04:00
David Gibson 73736280f9 Clean up the lua stack after EvalStringWithReturn's function creation 2022-07-27 19:18:26 -05:00
Goober5000 d5546f95e8 Merge pull request #4510 from Goober5000/warn_about_too_many_sexps
prevent too many dynamic SEXPs from breaking the SEXP system
2022-07-24 17:10:10 -04:00
Goober5000 29edfeedea display category name 2022-07-24 15:08:49 -04:00
Goober5000 8cf20b0175 prevent too many dynamic SEXPs from breaking the SEXP system
SEXP categories will not support more than 256 SEXPs; this is why the CHANGE2 category had to be created when CHANGE got full.  Unfortunately, dynamic SEXPs will count toward this limit, so mysterious errors will occur for the ones whose category indexes roll over.  The problem is not easily fixable, but at least the engine can detect the situation, warn about it, and refrain from adding any problematic SEXPs.

Since too many *total* SEXPs would cause a similar problem, this adds a warning for that case too.
2022-07-24 15:06:13 -04:00
Goober5000 c85040efc4 prevent a crash on game exit (#4507)
When `mission_campaign_clear()` is called, all persistent SEXP nodes (those used by the campaign) are marked as non-persistent.  When `sexp_shutdown()` was moved in #4503, this caused `Sexp_nodes` to be nullptr when the campaign was cleared, which caused a crash.  This reorders the shutdown functions to prevent the crash.
2022-07-22 20:39:20 -05:00
MageKing17 a16be863f3 Actually grab the object's type when doing type checks. (#4505)
PR #4500 added some checks, but accidentally compared `aip->target_objnum` to an object type (although the assertion message correctly retrieved the object type, leading to the bizarre assertion that `OBJ_SHIP`, i.e. 1, was an invalid target object type). This commit makes them all access the `Objects[]` array and retrieve the `.type`, just as the assertion message does (and the pre-#4500 conditional did).

Related to #4504, in that it's the source of the failed assertions, although I can't be sure it was the cause of the crashes without testing.
2022-07-20 21:08:40 -04:00
6 changed files with 53 additions and 20 deletions

No files matched your search

+2 -2
View File
@@ -10022,11 +10022,11 @@ void guard_object_was_hit(object *guard_objp, object *hitter_objp)
// This just checks to see that the target was a valid type. If it is not one of these, something really
// could be drastically wrong in the engine.
Assertion(aip->target_objnum == OBJ_SHIP || aip->target_objnum == OBJ_WEAPON || aip->target_objnum == OBJ_DEBRIS || aip->target_objnum == OBJ_ASTEROID || aip->target_objnum == OBJ_WAYPOINT,
Assertion(Objects[aip->target_objnum].type == OBJ_SHIP || Objects[aip->target_objnum].type == OBJ_WEAPON || Objects[aip->target_objnum].type == OBJ_DEBRIS || Objects[aip->target_objnum].type == OBJ_ASTEROID || Objects[aip->target_objnum].type == OBJ_WAYPOINT,
"This function just discovered that %s has an invalid target object type of %d. This is bad. Please report!",
Ships[aip->shipnum].ship_name, Objects[aip->target_objnum].type);
if (!(aip->target_objnum == OBJ_SHIP || aip->target_objnum == OBJ_WEAPON || aip->target_objnum == OBJ_ASTEROID || aip->target_objnum == OBJ_DEBRIS)){
if (!(Objects[aip->target_objnum].type == OBJ_SHIP || Objects[aip->target_objnum].type == OBJ_WEAPON || Objects[aip->target_objnum].type == OBJ_ASTEROID || Objects[aip->target_objnum].type == OBJ_DEBRIS)){
// it's probably a valid target, but retail would not count those cases, so just return.
return;
}
+15
View File
@@ -32318,6 +32318,21 @@ int get_category(int sexp_id)
return category;
}
// Goober5000
const char *get_category_name(int category_id)
{
if (category_id == OP_CATEGORY_CHANGE2)
category_id = OP_CATEGORY_CHANGE;
for (auto &category : op_menu)
{
if (category.id == category_id)
return category.name.c_str();
}
return "<unknown>";
}
// Goober5000
int category_of_subcategory(int subcategory_id)
{
+1
View File
@@ -1359,6 +1359,7 @@ void set_turret_secondary_ammo(ship_subsys *turret, int requested_bank, int requ
extern int get_category(int sexp_id);
extern int category_of_subcategory(int subcategory_id);
extern int get_subcategory(int sexp_id);
extern const char *get_category_name(int category_id);
// Goober5000
extern void sexp_music_close();
+16 -3
View File
@@ -125,8 +125,10 @@ void parse_sexp_table(const char* filename) {
luaSexp->parseTable();
int op = add_dynamic_sexp(std::move(instance), SEXP_GOAL_OPERATOR);
luaSexp->registerAIMode(op);
luaSexp->maybeRegisterPlayerOrder(op);
if (op >= 0) {
luaSexp->registerAIMode(op);
luaSexp->maybeRegisterPlayerOrder(op);
}
}
required_string("#End");
}
@@ -177,8 +179,19 @@ int add_dynamic_sexp(std::unique_ptr<DynamicSEXP>&& sexp, int type)
new_op.min = sexp->getMinimumArguments();
new_op.max = sexp->getMaximumArguments();
int free_op_index = get_next_free_operator(sexp->getCategory());
if (free_op_index >= 256) {
Warning(LOCATION, "There are too many SEXPs in the %s category. The SEXP %s will not be added.", get_category_name(sexp->getCategory()), sexp->getName().c_str());
return -1;
}
if (Operators.size() >= FIRST_OP) {
Warning(LOCATION, "There are too many total SEXPs. The SEXP %s will not be added.", sexp->getName().c_str());
return -1;
}
// For now, all dynamic SEXPS are only valid in missions
new_op.value = get_next_free_operator(sexp->getCategory()) | sexp->getCategory() | OP_NONCAMPAIGN_FLAG;
new_op.value = free_op_index | sexp->getCategory() | OP_NONCAMPAIGN_FLAG;
new_op.type = type;
global.operator_const_mapping.insert(std::make_pair(new_op.value, std::move(sexp)));
+6
View File
@@ -337,14 +337,20 @@ bool script_state::EvalStringWithReturn(const char* string, const char* format,
scripting::ade_get_args(LuaState, format, rtn);
}
} catch (const LuaException&) {
lua_pop(LuaState, 1);
return false;
}
} catch (const LuaException& e) {
LuaError(GetLuaSession(), "%s", e.what());
lua_pop(LuaState, 1);
return false;
}
lua_pop(LuaState, 1);
return true;
}
+13 -15
View File
@@ -6684,19 +6684,6 @@ void game_shutdown(void)
gr_flip();
}
// Free SEXP resources
sexp_shutdown();
// Free the scripting resources of the new UI first
scpui::shutdown_scripting();
// Everything after this should be done without scripting so we can free those resources here. By this point, all things that hold Lua References must be destroyed (such as Lua SEXPs)
Script_system.Clear();
// Deinitialize the new UI system, needs to be done after scripting shutdown to make sure the resources were
// released properly
scpui::shutdown();
// if the player has left the "player select" screen and quit the game without actually choosing
// a player, Player will be nullptr, in which case we shouldn't write the player file out!
if (!(Game_mode & GM_STANDALONE_SERVER) && (Player!=nullptr) && !Is_standalone){
@@ -6732,7 +6719,6 @@ void game_shutdown(void)
scoring_close();
stars_close(); // clean out anything used by stars code
// the menu close functions will unload the bitmaps if they were displayed during the game
@@ -6742,6 +6728,19 @@ void game_shutdown(void)
// free left over memory from table parsing
player_tips_close();
// more fundamental shutdowns begin here ----------
sexp_shutdown(); // Free SEXP resources
scpui::shutdown_scripting(); // Free the scripting resources of the new UI first
Script_system.Clear(); // Everything after this should be done without scripting so we can free those resources here.
// By this point, all things that hold Lua References must be destroyed (such as Lua SEXPs)
scpui::shutdown(); // Deinitialize the new UI system, needs to be done after scripting shutdown to make sure the resources were released properly
control_config_common_close();
io::joystick::shutdown();
@@ -6780,7 +6779,6 @@ void game_shutdown(void)
}
lcl_xstr_close();
}
// game_stop_looped_sounds()