summaryrefslogtreecommitdiff
path: root/src/script/api
diff options
context:
space:
mode:
authortruebrain <truebrain@openttd.org>2012-01-03 16:36:24 +0000
committertruebrain <truebrain@openttd.org>2012-01-03 16:36:24 +0000
commit34d90da509a27c4abe35c11d7f034b1e386cd968 (patch)
tree552a11c264ee5b26ad849818f50f45bf9927735c /src/script/api
parent18ac3f2bd89aa11fefa64bdada287a72937ab8d5 (diff)
downloadopenttd-34d90da509a27c4abe35c11d7f034b1e386cd968.tar.xz
(svn r23731) -Add: add GSGoal::Question(), to ask a question to a(ll) company(ies). It can contain random text, and at most 3 buttons from a collection of 17
Diffstat (limited to 'src/script/api')
-rw-r--r--src/script/api/ai/ai_event.hpp.sq1
-rw-r--r--src/script/api/game/game_event.hpp.sq1
-rw-r--r--src/script/api/game/game_event_types.hpp.sq17
-rw-r--r--src/script/api/game/game_goal.hpp.sq40
-rw-r--r--src/script/api/script_event.hpp1
-rw-r--r--src/script/api/script_event_types.hpp50
-rw-r--r--src/script/api/script_goal.cpp25
-rw-r--r--src/script/api/script_goal.hpp52
-rw-r--r--src/script/api/template/template_event_types.hpp.sq9
-rw-r--r--src/script/api/template/template_goal.hpp.sq2
10 files changed, 188 insertions, 10 deletions
diff --git a/src/script/api/ai/ai_event.hpp.sq b/src/script/api/ai/ai_event.hpp.sq
index e18845188..7fcaa7b81 100644
--- a/src/script/api/ai/ai_event.hpp.sq
+++ b/src/script/api/ai/ai_event.hpp.sq
@@ -47,6 +47,7 @@ void SQAIEvent_Register(Squirrel *engine)
SQAIEvent.DefSQConst(engine, ScriptEvent::ET_AIRCRAFT_DEST_TOO_FAR, "ET_AIRCRAFT_DEST_TOO_FAR");
SQAIEvent.DefSQConst(engine, ScriptEvent::ET_ADMIN_PORT, "ET_ADMIN_PORT");
SQAIEvent.DefSQConst(engine, ScriptEvent::ET_WINDOW_WIDGET_CLICK, "ET_WINDOW_WIDGET_CLICK");
+ SQAIEvent.DefSQConst(engine, ScriptEvent::ET_GOAL_QUESTION_ANSWER, "ET_GOAL_QUESTION_ANSWER");
SQAIEvent.DefSQMethod(engine, &ScriptEvent::GetEventType, "GetEventType", 1, "x");
diff --git a/src/script/api/game/game_event.hpp.sq b/src/script/api/game/game_event.hpp.sq
index 1ac964518..396295530 100644
--- a/src/script/api/game/game_event.hpp.sq
+++ b/src/script/api/game/game_event.hpp.sq
@@ -47,6 +47,7 @@ void SQGSEvent_Register(Squirrel *engine)
SQGSEvent.DefSQConst(engine, ScriptEvent::ET_AIRCRAFT_DEST_TOO_FAR, "ET_AIRCRAFT_DEST_TOO_FAR");
SQGSEvent.DefSQConst(engine, ScriptEvent::ET_ADMIN_PORT, "ET_ADMIN_PORT");
SQGSEvent.DefSQConst(engine, ScriptEvent::ET_WINDOW_WIDGET_CLICK, "ET_WINDOW_WIDGET_CLICK");
+ SQGSEvent.DefSQConst(engine, ScriptEvent::ET_GOAL_QUESTION_ANSWER, "ET_GOAL_QUESTION_ANSWER");
SQGSEvent.DefSQMethod(engine, &ScriptEvent::GetEventType, "GetEventType", 1, "x");
diff --git a/src/script/api/game/game_event_types.hpp.sq b/src/script/api/game/game_event_types.hpp.sq
index 25734cdaf..727e90bb1 100644
--- a/src/script/api/game/game_event_types.hpp.sq
+++ b/src/script/api/game/game_event_types.hpp.sq
@@ -249,3 +249,20 @@ void SQGSEventWindowWidgetClick_Register(Squirrel *engine)
SQGSEventWindowWidgetClick.PostRegister(engine);
}
+
+
+template <> const char *GetClassName<ScriptEventGoalQuestionAnswer, ST_GS>() { return "GSEventGoalQuestionAnswer"; }
+
+void SQGSEventGoalQuestionAnswer_Register(Squirrel *engine)
+{
+ DefSQClass<ScriptEventGoalQuestionAnswer, ST_GS> SQGSEventGoalQuestionAnswer("GSEventGoalQuestionAnswer");
+ SQGSEventGoalQuestionAnswer.PreRegister(engine, "GSEvent");
+
+ SQGSEventGoalQuestionAnswer.DefSQStaticMethod(engine, &ScriptEventGoalQuestionAnswer::Convert, "Convert", 2, ".x");
+
+ SQGSEventGoalQuestionAnswer.DefSQMethod(engine, &ScriptEventGoalQuestionAnswer::GetUniqueID, "GetUniqueID", 1, "x");
+ SQGSEventGoalQuestionAnswer.DefSQMethod(engine, &ScriptEventGoalQuestionAnswer::GetCompany, "GetCompany", 1, "x");
+ SQGSEventGoalQuestionAnswer.DefSQMethod(engine, &ScriptEventGoalQuestionAnswer::GetButton, "GetButton", 1, "x");
+
+ SQGSEventGoalQuestionAnswer.PostRegister(engine);
+}
diff --git a/src/script/api/game/game_goal.hpp.sq b/src/script/api/game/game_goal.hpp.sq
index 54b1c6aeb..22ed685b6 100644
--- a/src/script/api/game/game_goal.hpp.sq
+++ b/src/script/api/game/game_goal.hpp.sq
@@ -21,16 +21,36 @@ void SQGSGoal_Register(Squirrel *engine)
SQGSGoal.PreRegister(engine);
SQGSGoal.AddConstructor<void (ScriptGoal::*)(), 1>(engine, "x");
- SQGSGoal.DefSQConst(engine, ScriptGoal::GOAL_INVALID, "GOAL_INVALID");
- SQGSGoal.DefSQConst(engine, ScriptGoal::GT_NONE, "GT_NONE");
- SQGSGoal.DefSQConst(engine, ScriptGoal::GT_TILE, "GT_TILE");
- SQGSGoal.DefSQConst(engine, ScriptGoal::GT_INDUSTRY, "GT_INDUSTRY");
- SQGSGoal.DefSQConst(engine, ScriptGoal::GT_TOWN, "GT_TOWN");
- SQGSGoal.DefSQConst(engine, ScriptGoal::GT_COMPANY, "GT_COMPANY");
-
- SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::IsValidGoal, "IsValidGoal", 2, ".i");
- SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::New, "New", 5, ".i.ii");
- SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::Remove, "Remove", 2, ".i");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::GOAL_INVALID, "GOAL_INVALID");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::GT_NONE, "GT_NONE");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::GT_TILE, "GT_TILE");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::GT_INDUSTRY, "GT_INDUSTRY");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::GT_TOWN, "GT_TOWN");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::GT_COMPANY, "GT_COMPANY");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::BUTTON_CANCEL, "BUTTON_CANCEL");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::BUTTON_OK, "BUTTON_OK");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::BUTTON_NO, "BUTTON_NO");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::BUTTON_YES, "BUTTON_YES");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::BUTTON_DECLINE, "BUTTON_DECLINE");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::BUTTON_ACCEPT, "BUTTON_ACCEPT");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::BUTTON_IGNORE, "BUTTON_IGNORE");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::BUTTON_RETRY, "BUTTON_RETRY");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::BUTTON_PREVIOUS, "BUTTON_PREVIOUS");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::BUTTON_NEXT, "BUTTON_NEXT");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::BUTTON_STOP, "BUTTON_STOP");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::BUTTON_START, "BUTTON_START");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::BUTTON_GO, "BUTTON_GO");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::BUTTON_CONTINUE, "BUTTON_CONTINUE");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::BUTTON_RESTART, "BUTTON_RESTART");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::BUTTON_POSTPONE, "BUTTON_POSTPONE");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::BUTTON_SURRENDER, "BUTTON_SURRENDER");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::BUTTON_CLOSE, "BUTTON_CLOSE");
+
+ SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::IsValidGoal, "IsValidGoal", 2, ".i");
+ SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::New, "New", 5, ".i.ii");
+ SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::Remove, "Remove", 2, ".i");
+ SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::Question, "Question", 5, ".ii.i");
+ SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::CloseQuestion, "CloseQuestion", 2, ".i");
SQGSGoal.PostRegister(engine);
}
diff --git a/src/script/api/script_event.hpp b/src/script/api/script_event.hpp
index db8657b53..96e7df377 100644
--- a/src/script/api/script_event.hpp
+++ b/src/script/api/script_event.hpp
@@ -52,6 +52,7 @@ public:
ET_AIRCRAFT_DEST_TOO_FAR,
ET_ADMIN_PORT,
ET_WINDOW_WIDGET_CLICK,
+ ET_GOAL_QUESTION_ANSWER,
};
/**
diff --git a/src/script/api/script_event_types.hpp b/src/script/api/script_event_types.hpp
index a33d68524..9bce59318 100644
--- a/src/script/api/script_event_types.hpp
+++ b/src/script/api/script_event_types.hpp
@@ -14,6 +14,7 @@
#include "script_event.hpp"
#include "script_company.hpp"
+#include "script_goal.hpp"
#include "script_window.hpp"
/**
@@ -932,4 +933,53 @@ private:
uint8 widget; ///< Widget of the click.
};
+/**
+ * Event Goal Question Answer, where you receive the answer given to your questions.
+ * @note It is possible that you get more than 1 answer from the same company
+ * (due to lag). Please keep this in mind while handling this event.
+ * @api game
+ */
+class ScriptEventGoalQuestionAnswer : public ScriptEvent {
+public:
+ /**
+ * @param uniqueid The uniqueID you have given this question.
+ * @param company The company that is replying.
+ * @param button The button the company pressed.
+ */
+ ScriptEventGoalQuestionAnswer(uint16 uniqueid, ScriptCompany::CompanyID company, ScriptGoal::QuestionButton button) :
+ ScriptEvent(ET_GOAL_QUESTION_ANSWER),
+ uniqueid(uniqueid),
+ company(company),
+ button(button)
+ {}
+
+ /**
+ * Convert an ScriptEvent to the real instance.
+ * @param instance The instance to convert.
+ * @return The converted instance.
+ */
+ static ScriptEventGoalQuestionAnswer *Convert(ScriptEvent *instance) { return (ScriptEventGoalQuestionAnswer *)instance; }
+
+ /**
+ * Get the unique id of the question.
+ */
+ uint16 GetUniqueID() { return this->uniqueid; }
+
+ /**
+ * Get the company that pressed a button.
+ */
+ ScriptCompany::CompanyID GetCompany() { return this->company; }
+
+ /**
+ * Get the button that got pressed.
+ */
+ ScriptGoal::QuestionButton GetButton() { return this->button; }
+
+private:
+ uint16 uniqueid; ///< The uniqueid of the question.
+ ScriptCompany::CompanyID company; ///< The company given the answer.
+ ScriptGoal::QuestionButton button; ///< The button he pressed.
+};
+
+
#endif /* SCRIPT_EVENT_TYPES_HPP */
diff --git a/src/script/api/script_goal.cpp b/src/script/api/script_goal.cpp
index e005ceda0..ba5e19e37 100644
--- a/src/script/api/script_goal.cpp
+++ b/src/script/api/script_goal.cpp
@@ -32,6 +32,7 @@
{
CCountedPtr<Text> counter(goal);
+ EnforcePrecondition(GOAL_INVALID, ScriptObject::GetCompany() == OWNER_DEITY);
EnforcePrecondition(GOAL_INVALID, goal != NULL);
EnforcePrecondition(GOAL_INVALID, !StrEmpty(goal->GetEncodedText()));
EnforcePrecondition(GOAL_INVALID, company == ScriptCompany::COMPANY_INVALID || ScriptCompany::ResolveCompanyID(company) != ScriptCompany::COMPANY_INVALID);
@@ -48,7 +49,31 @@
/* static */ bool ScriptGoal::Remove(GoalID goal_id)
{
+ EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY);
EnforcePrecondition(false, IsValidGoal(goal_id));
return ScriptObject::DoCommand(0, goal_id, 0, CMD_REMOVE_GOAL);
}
+
+/* static */ bool ScriptGoal::Question(uint16 uniqueid, ScriptCompany::CompanyID company, Text *question, int buttons)
+{
+ CCountedPtr<Text> counter(question);
+
+ EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY);
+ EnforcePrecondition(false, question != NULL);
+ EnforcePrecondition(false, !StrEmpty(question->GetEncodedText()));
+ EnforcePrecondition(false, company == ScriptCompany::COMPANY_INVALID || ScriptCompany::ResolveCompanyID(company) != ScriptCompany::COMPANY_INVALID);
+ EnforcePrecondition(false, CountBits(buttons) >= 1 && CountBits(buttons) <= 3);
+
+ uint8 c = company;
+ if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY;
+
+ return ScriptObject::DoCommand(0, uniqueid | (c << 16), buttons, CMD_GOAL_QUESTION, question->GetEncodedText());
+}
+
+/* static */ bool ScriptGoal::CloseQuestion(uint16 uniqueid)
+{
+ EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY);
+
+ return ScriptObject::DoCommand(0, uniqueid, 0, CMD_GOAL_QUESTION_ANSWER);
+}
diff --git a/src/script/api/script_goal.hpp b/src/script/api/script_goal.hpp
index 2fad1e843..ee0077663 100644
--- a/src/script/api/script_goal.hpp
+++ b/src/script/api/script_goal.hpp
@@ -42,6 +42,28 @@ public:
GT_COMPANY = ::GT_COMPANY, ///< Destination is a company.
};
+ enum QuestionButton {
+ /* Note: these values represent part of the string list starting with STR_GOAL_QUESTION_BUTTON_CANCEL */
+ BUTTON_CANCEL = (1 << 0), ///< Cancel button.
+ BUTTON_OK = (1 << 1), ///< OK button.
+ BUTTON_NO = (1 << 2), ///< No button.
+ BUTTON_YES = (1 << 3), ///< Yes button.
+ BUTTON_DECLINE = (1 << 4), ///< Decline button.
+ BUTTON_ACCEPT = (1 << 5), ///< Accept button.
+ BUTTON_IGNORE = (1 << 6), ///< Ignore button.
+ BUTTON_RETRY = (1 << 7), ///< Retry button.
+ BUTTON_PREVIOUS = (1 << 8), ///< Previous button.
+ BUTTON_NEXT = (1 << 9), ///< Next button.
+ BUTTON_STOP = (1 << 10), ///< Stop button.
+ BUTTON_START = (1 << 11), ///< Start button.
+ BUTTON_GO = (1 << 12), ///< Go button.
+ BUTTON_CONTINUE = (1 << 13), ///< Continue button.
+ BUTTON_RESTART = (1 << 14), ///< Restart button.
+ BUTTON_POSTPONE = (1 << 15), ///< Postpone button.
+ BUTTON_SURRENDER = (1 << 16), ///< Surrender button.
+ BUTTON_CLOSE = (1 << 17), ///< Close button.
+ };
+
/**
* Check whether this is a valid goalID.
* @param goal_id The GoalID to check.
@@ -56,6 +78,7 @@ public:
* @param type The type of the goal.
* @param destination The destination of the #type type.
* @return The new GoalID, or GOAL_INVALID if it failed.
+ * @pre No ScriptCompanyMode may be in scope.
* @pre goal != NULL && len(goal) != 0.
* @pre company == COMPANY_INVALID || ResolveCompanyID(company) != COMPANY_INVALID.
*/
@@ -65,9 +88,38 @@ public:
* Remove a goal from the list.
* @param goal_id The goal to remove.
* @return True if the action succeeded.
+ * @pre No ScriptCompanyMode may be in scope.
* @pre IsValidGoal(goal_id).
*/
static bool Remove(GoalID goal_id);
+
+ /**
+ * Ask a question.
+ * @param uniqueid Your unique id to distinguish results of multiple questions in the returning event.
+ * @param company The company to ask the question, or ScriptCompany::COMPANY_INVALID for all.
+ * @param question The question to ask (can be either a raw string, or a ScriptText object).
+ * @param buttons Any combinations (at least 1, up to 3) of buttons defined in QuestionButton. Like BUTTON_YES + BUTTON_NO.
+ * @return True if the action succeeded.
+ * @pre No ScriptCompanyMode may be in scope.
+ * @pre question != NULL && len(question) != 0.
+ * @pre company == COMPANY_INVALID || ResolveCompanyID(company) != COMPANY_INVALID.
+ * @pre CountBits(buttons) >= 1 && CountBits(buttons) <= 3.
+ * @note Replies to the question are given by you via the event ScriptEvent_GoalQuestionAnswer.
+ * @note There is no guarantee you ever get a reply on your question.
+ */
+ static bool Question(uint16 uniqueid, ScriptCompany::CompanyID company, Text *question, int buttons);
+
+ /**
+ * Close the question on all clients.
+ * @param uniqueid The uniqueid of the question you want to close.
+ * @return True if the action succeeded.
+ * @pre No ScriptCompanyMode may be in scope.
+ * @note If you send a question to a single company, and get a reply for them,
+ * the question is already closed on all clients. Only use this function if
+ * you want to timeout a question, or if you send the question to all
+ * companies, but you are only interested in the reply of the first.
+ */
+ static bool CloseQuestion(uint16 uniqueid);
};
#endif /* SCRIPT_GOAL_HPP */
diff --git a/src/script/api/template/template_event_types.hpp.sq b/src/script/api/template/template_event_types.hpp.sq
index 264ec5d8a..e03e7df3d 100644
--- a/src/script/api/template/template_event_types.hpp.sq
+++ b/src/script/api/template/template_event_types.hpp.sq
@@ -230,3 +230,12 @@ namespace SQConvert {
template <> inline const ScriptEventWindowWidgetClick &GetParam(ForceType<const ScriptEventWindowWidgetClick &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(ScriptEventWindowWidgetClick *)instance; }
template <> inline int Return<ScriptEventWindowWidgetClick *>(HSQUIRRELVM vm, ScriptEventWindowWidgetClick *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "EventWindowWidgetClick", res, NULL, DefSQDestructorCallback<ScriptEventWindowWidgetClick>, true); return 1; }
} // namespace SQConvert
+
+namespace SQConvert {
+ /* Allow ScriptEventGoalQuestionAnswer to be used as Squirrel parameter */
+ template <> inline ScriptEventGoalQuestionAnswer *GetParam(ForceType<ScriptEventGoalQuestionAnswer *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (ScriptEventGoalQuestionAnswer *)instance; }
+ template <> inline ScriptEventGoalQuestionAnswer &GetParam(ForceType<ScriptEventGoalQuestionAnswer &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(ScriptEventGoalQuestionAnswer *)instance; }
+ template <> inline const ScriptEventGoalQuestionAnswer *GetParam(ForceType<const ScriptEventGoalQuestionAnswer *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (ScriptEventGoalQuestionAnswer *)instance; }
+ template <> inline const ScriptEventGoalQuestionAnswer &GetParam(ForceType<const ScriptEventGoalQuestionAnswer &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(ScriptEventGoalQuestionAnswer *)instance; }
+ template <> inline int Return<ScriptEventGoalQuestionAnswer *>(HSQUIRRELVM vm, ScriptEventGoalQuestionAnswer *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "EventGoalQuestionAnswer", res, NULL, DefSQDestructorCallback<ScriptEventGoalQuestionAnswer>, true); return 1; }
+} // namespace SQConvert
diff --git a/src/script/api/template/template_goal.hpp.sq b/src/script/api/template/template_goal.hpp.sq
index 012864324..881f05b7e 100644
--- a/src/script/api/template/template_goal.hpp.sq
+++ b/src/script/api/template/template_goal.hpp.sq
@@ -17,6 +17,8 @@ namespace SQConvert {
template <> inline int Return<ScriptGoal::GoalID>(HSQUIRRELVM vm, ScriptGoal::GoalID res) { sq_pushinteger(vm, (int32)res); return 1; }
template <> inline ScriptGoal::GoalType GetParam(ForceType<ScriptGoal::GoalType>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptGoal::GoalType)tmp; }
template <> inline int Return<ScriptGoal::GoalType>(HSQUIRRELVM vm, ScriptGoal::GoalType res) { sq_pushinteger(vm, (int32)res); return 1; }
+ template <> inline ScriptGoal::QuestionButton GetParam(ForceType<ScriptGoal::QuestionButton>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptGoal::QuestionButton)tmp; }
+ template <> inline int Return<ScriptGoal::QuestionButton>(HSQUIRRELVM vm, ScriptGoal::QuestionButton res) { sq_pushinteger(vm, (int32)res); return 1; }
/* Allow ScriptGoal to be used as Squirrel parameter */
template <> inline ScriptGoal *GetParam(ForceType<ScriptGoal *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (ScriptGoal *)instance; }