Changeset - r27553:ad2bff42f7f5
[Not reviewed]
master
0 7 0
mrmbernardi - 11 months ago 2023-06-08 17:00:31
mrmbernardi@gmail.com
Feature: [GS] Goal destination can be updated (#10817)
7 files changed with 113 insertions and 44 deletions:
0 comments (0 inline, 0 general)
src/command_type.h
Show inline comments
 
@@ -295,6 +295,7 @@ enum Commands : uint16 {
 
	CMD_CUSTOM_NEWS_ITEM,             ///< create a custom news message
 
	CMD_CREATE_GOAL,                  ///< create a new goal
 
	CMD_REMOVE_GOAL,                  ///< remove a goal
 
	CMD_SET_GOAL_DESTINATION,         ///< update goal destination of a goal
 
	CMD_SET_GOAL_TEXT,                ///< update goal text of a goal
 
	CMD_SET_GOAL_PROGRESS,            ///< update goal progress text of a goal
 
	CMD_SET_GOAL_COMPLETED,           ///< update goal completed status of a goal
src/goal.cpp
Show inline comments
 
@@ -31,6 +31,41 @@
 
GoalPool _goal_pool("Goal");
 
INSTANTIATE_POOL_METHODS(Goal)
 

	
 
/* static */ bool Goal::IsValidGoalDestination(CompanyID company, GoalType type, GoalTypeID dest)
 
{
 
	switch (type) {
 
		case GT_NONE:
 
			if (dest != 0) return false;
 
			break;
 

	
 
		case GT_TILE:
 
			if (!IsValidTile(dest)) return false;
 
			break;
 

	
 
		case GT_INDUSTRY:
 
			if (!Industry::IsValidID(dest)) return false;
 
			break;
 

	
 
		case GT_TOWN:
 
			if (!Town::IsValidID(dest)) return false;
 
			break;
 

	
 
		case GT_COMPANY:
 
			if (!Company::IsValidID(dest)) return false;
 
			break;
 

	
 
		case GT_STORY_PAGE: {
 
			if (!StoryPage::IsValidID(dest)) return false;
 
			CompanyID story_company = StoryPage::Get(dest)->company;
 
			if (company == INVALID_COMPANY ? story_company != INVALID_COMPANY : story_company != INVALID_COMPANY && story_company != company) return false;
 
			break;
 
		}
 

	
 
		default: return false;
 
	}
 
	return true;
 
}
 

	
 
/**
 
 * Create a new goal.
 
 * @param flags type of operation
 
@@ -47,37 +82,7 @@ std::tuple<CommandCost, GoalID> CmdCreat
 
	if (_current_company != OWNER_DEITY) return { CMD_ERROR, INVALID_GOAL };
 
	if (text.empty()) return { CMD_ERROR, INVALID_GOAL };
 
	if (company != INVALID_COMPANY && !Company::IsValidID(company)) return { CMD_ERROR, INVALID_GOAL };
 

	
 
	switch (type) {
 
		case GT_NONE:
 
			if (dest != 0) return { CMD_ERROR, INVALID_GOAL };
 
			break;
 

	
 
		case GT_TILE:
 
			if (!IsValidTile(dest)) return { CMD_ERROR, INVALID_GOAL };
 
			break;
 

	
 
		case GT_INDUSTRY:
 
			if (!Industry::IsValidID(dest)) return { CMD_ERROR, INVALID_GOAL };
 
			break;
 

	
 
		case GT_TOWN:
 
			if (!Town::IsValidID(dest)) return { CMD_ERROR, INVALID_GOAL };
 
			break;
 

	
 
		case GT_COMPANY:
 
			if (!Company::IsValidID(dest)) return { CMD_ERROR, INVALID_GOAL };
 
			break;
 

	
 
		case GT_STORY_PAGE: {
 
			if (!StoryPage::IsValidID(dest)) return { CMD_ERROR, INVALID_GOAL };
 
			CompanyID story_company = StoryPage::Get(dest)->company;
 
			if (company == INVALID_COMPANY ? story_company != INVALID_COMPANY : story_company != INVALID_COMPANY && story_company != company) return { CMD_ERROR, INVALID_GOAL };
 
			break;
 
		}
 

	
 
		default: return { CMD_ERROR, INVALID_GOAL };
 
	}
 
	if (!Goal::IsValidGoalDestination(company, type, dest)) return { CMD_ERROR, INVALID_GOAL };
 

	
 
	if (flags & DC_EXEC) {
 
		Goal *g = new Goal();
 
@@ -128,6 +133,29 @@ CommandCost CmdRemoveGoal(DoCommandFlag 
 
}
 

	
 
/**
 
 * Update goal destination of a goal.
 
 * @param flags type of operation
 
 * @param goal GoalID to update.
 
 * @param type GoalType of destination.
 
 * @param dest GoalTypeID of destination.
 
 * @return the cost of this operation or an error
 
 */
 
CommandCost CmdSetGoalDestination(DoCommandFlag flags, GoalID goal, GoalType type, GoalTypeID dest)
 
{
 
	if (_current_company != OWNER_DEITY) return CMD_ERROR;
 
	if (!Goal::IsValidID(goal)) return CMD_ERROR;
 
	Goal *g = Goal::Get(goal);
 
	if (!Goal::IsValidGoalDestination(g->company, type, dest)) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		g->type = type;
 
		g->dst = dest;
 
	}
 

	
 
	return CommandCost();
 
}
 

	
 
/**
 
 * Update goal text of a goal.
 
 * @param flags type of operation
 
 * @param goal GoalID to update.
src/goal_base.h
Show inline comments
 
@@ -35,6 +35,8 @@ struct Goal : GoalPool::PoolItem<&_goal_
 
	 * (Empty) destructor has to be defined else operator delete might be called with nullptr parameter
 
	 */
 
	inline ~Goal() { }
 

	
 
	static bool IsValidGoalDestination(CompanyID company, GoalType type, GoalTypeID dest);
 
};
 

	
 
#endif /* GOAL_BASE_H */
src/goal_cmd.h
Show inline comments
 
@@ -15,6 +15,7 @@
 

	
 
std::tuple<CommandCost, GoalID> CmdCreateGoal(DoCommandFlag flags, CompanyID company, GoalType type, GoalTypeID dest, const std::string &text);
 
CommandCost CmdRemoveGoal(DoCommandFlag flags, GoalID goal);
 
CommandCost CmdSetGoalDestination(DoCommandFlag flags, GoalID goal, GoalType type, GoalTypeID dest);
 
CommandCost CmdSetGoalText(DoCommandFlag flags, GoalID goal, const std::string &text);
 
CommandCost CmdSetGoalProgress(DoCommandFlag flags, GoalID goal, const std::string &text);
 
CommandCost CmdSetGoalCompleted(DoCommandFlag flags, GoalID goal, bool completed);
 
@@ -23,6 +24,7 @@ CommandCost CmdGoalQuestionAnswer(DoComm
 

	
 
DEF_CMD_TRAIT(CMD_CREATE_GOAL,          CmdCreateGoal,         CMD_DEITY | CMD_STR_CTRL, CMDT_OTHER_MANAGEMENT)
 
DEF_CMD_TRAIT(CMD_REMOVE_GOAL,          CmdRemoveGoal,         CMD_DEITY,                CMDT_OTHER_MANAGEMENT)
 
DEF_CMD_TRAIT(CMD_SET_GOAL_DESTINATION, CmdSetGoalDestination, CMD_DEITY | CMD_STR_CTRL, CMDT_OTHER_MANAGEMENT)
 
DEF_CMD_TRAIT(CMD_SET_GOAL_TEXT,        CmdSetGoalText,        CMD_DEITY | CMD_STR_CTRL, CMDT_OTHER_MANAGEMENT)
 
DEF_CMD_TRAIT(CMD_SET_GOAL_PROGRESS,    CmdSetGoalProgress,    CMD_DEITY | CMD_STR_CTRL, CMDT_OTHER_MANAGEMENT)
 
DEF_CMD_TRAIT(CMD_SET_GOAL_COMPLETED,   CmdSetGoalCompleted,   CMD_DEITY | CMD_STR_CTRL, CMDT_OTHER_MANAGEMENT)
src/script/api/game_changelog.hpp
Show inline comments
 
@@ -75,6 +75,8 @@
 
 * \li GSGroupList
 
 * \li GSVehicleList_Group
 
 * \li GSVehicleList_DefaultGroup
 
 * \li GSGoal::IsValidGoalDestination
 
 * \li GSGoal::SetDestination
 
 *
 
 * API removals:
 
 * \li GSError::ERR_PRECONDITION_TOO_MANY_PARAMETERS, that error is never returned anymore.
src/script/api/script_goal.cpp
Show inline comments
 
@@ -28,6 +28,20 @@
 
	return ::Goal::IsValidID(goal_id);
 
}
 

	
 
/* static */ bool ScriptGoal::IsValidGoalDestination(ScriptCompany::CompanyID company, GoalType type, SQInteger destination)
 
{
 
	CompanyID c = (::CompanyID)company;
 
	if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY;
 
	StoryPage *story_page = nullptr;
 
	if (type == GT_STORY_PAGE && ScriptStoryPage::IsValidStoryPage((ScriptStoryPage::StoryPageID)destination)) story_page = ::StoryPage::Get((ScriptStoryPage::StoryPageID)destination);
 
	return (type == GT_NONE && destination == 0) ||
 
			(type == GT_TILE && ScriptMap::IsValidTile(destination)) ||
 
			(type == GT_INDUSTRY && ScriptIndustry::IsValidIndustry(destination)) ||
 
			(type == GT_TOWN && ScriptTown::IsValidTown(destination)) ||
 
			(type == GT_COMPANY && ScriptCompany::ResolveCompanyID((ScriptCompany::CompanyID)destination) != ScriptCompany::COMPANY_INVALID) ||
 
			(type == GT_STORY_PAGE && story_page != nullptr && (c == INVALID_COMPANY ? story_page->company == INVALID_COMPANY : story_page->company == INVALID_COMPANY || story_page->company == c));
 
}
 

	
 
/* static */ ScriptGoal::GoalID ScriptGoal::New(ScriptCompany::CompanyID company, Text *goal, GoalType type, SQInteger destination)
 
{
 
	CCountedPtr<Text> counter(goal);
 
@@ -37,20 +51,9 @@
 
	const std::string &text = goal->GetEncodedText();
 
	EnforcePreconditionEncodedText(GOAL_INVALID, text);
 
	EnforcePrecondition(GOAL_INVALID, company == ScriptCompany::COMPANY_INVALID || ScriptCompany::ResolveCompanyID(company) != ScriptCompany::COMPANY_INVALID);
 

	
 
	CompanyID c = (::CompanyID)company;
 
	if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY;
 
	StoryPage *story_page = nullptr;
 
	if (type == GT_STORY_PAGE && ScriptStoryPage::IsValidStoryPage((ScriptStoryPage::StoryPageID)destination)) story_page = ::StoryPage::Get((ScriptStoryPage::StoryPageID)destination);
 
	EnforcePrecondition(GOAL_INVALID, IsValidGoalDestination(company, type, destination));
 

	
 
	EnforcePrecondition(GOAL_INVALID, (type == GT_NONE && destination == 0) ||
 
			(type == GT_TILE && ScriptMap::IsValidTile(destination)) ||
 
			(type == GT_INDUSTRY && ScriptIndustry::IsValidIndustry(destination)) ||
 
			(type == GT_TOWN && ScriptTown::IsValidTown(destination)) ||
 
			(type == GT_COMPANY && ScriptCompany::ResolveCompanyID((ScriptCompany::CompanyID)destination) != ScriptCompany::COMPANY_INVALID) ||
 
			(type == GT_STORY_PAGE && story_page != nullptr && (c == INVALID_COMPANY ? story_page->company == INVALID_COMPANY : story_page->company == INVALID_COMPANY || story_page->company == c)));
 

	
 
	if (!ScriptObject::Command<CMD_CREATE_GOAL>::Do(&ScriptInstance::DoCommandReturnGoalID, c, (::GoalType)type, destination, text)) return GOAL_INVALID;
 
	if (!ScriptObject::Command<CMD_CREATE_GOAL>::Do(&ScriptInstance::DoCommandReturnGoalID, (::CompanyID)company, (::GoalType)type, destination, text)) return GOAL_INVALID;
 

	
 
	/* In case of test-mode, we return GoalID 0 */
 
	return (ScriptGoal::GoalID)0;
 
@@ -64,6 +67,16 @@
 
	return ScriptObject::Command<CMD_REMOVE_GOAL>::Do(goal_id);
 
}
 

	
 
/* static */ bool ScriptGoal::SetDestination(GoalID goal_id, GoalType type, SQInteger destination)
 
{
 
	EnforceDeityMode(false);
 
	EnforcePrecondition(false, IsValidGoal(goal_id));
 
	Goal *g = Goal::Get(goal_id);
 
	EnforcePrecondition(false, IsValidGoalDestination((ScriptCompany::CompanyID)g->company, type, destination));
 

	
 
	return ScriptObject::Command<CMD_SET_GOAL_DESTINATION>::Do(goal_id, (::GoalType)type, destination);
 
}
 

	
 
/* static */ bool ScriptGoal::SetText(GoalID goal_id, Text *goal)
 
{
 
	CCountedPtr<Text> counter(goal);
src/script/api/script_goal.hpp
Show inline comments
 
@@ -90,6 +90,15 @@ public:
 
	static bool IsValidGoal(GoalID goal_id);
 

	
 
	/**
 
	 * Check whether this is a valid goal destination.
 
	 * @param company The relevant company if a story page is the destination.
 
	 * @param type The type of the goal.
 
	 * @param destination The destination of the \a type type.
 
	 * @return True if and only if this goal destination is valid.
 
	 */
 
	static bool IsValidGoalDestination(ScriptCompany::CompanyID company, GoalType type, SQInteger destination);
 

	
 
	/**
 
	 * Create a new goal.
 
	 * @param company The company to create the goal for, or ScriptCompany::COMPANY_INVALID for all.
 
	 * @param goal The goal to add to the GUI (can be either a raw string, or a ScriptText object).
 
@@ -115,6 +124,18 @@ public:
 
	static bool Remove(GoalID goal_id);
 

	
 
	/**
 
	 * Update goal destination of a goal.
 
	 * @param goal_id The goal to update.
 
	 * @param type The type of the goal.
 
	 * @param destination The destination of the \a type type.
 
	 * @return True if the action succeeded.
 
	 * @pre ScriptCompanyMode::IsDeity().
 
	 * @pre IsValidGoal(goal_id).
 
	 * @pre IsValidGoalDestination(g->company, type, destination).
 
	 */
 
	static bool SetDestination(GoalID goal_id, GoalType type, SQInteger destination);
 

	
 
	/**
 
	 * Update goal text of a goal.
 
	 * @param goal_id The goal to update.
 
	 * @param goal The new goal text (can be either a raw string, or a ScriptText object).
0 comments (0 inline, 0 general)