void ScriptExecMode::FinalRelease() { if (this->GetDoCommandModeInstance() != this) { /* Ignore this error if the script already died. */ if (!ScriptObject::GetActiveInstance()->IsDead()) { throw Script_FatalError("ScriptExecMode object was removed while it was not the latest *Mode object created."); } } }
ScriptExecMode::~ScriptExecMode() { if (this->GetDoCommandModeInstance() != this) { /* Ignore this error if the AI already died. */ if (!ScriptObject::GetActiveInstance()->IsDead()) { throw Script_FatalError("ScriptExecMode object was removed while it was not the latest AI*Mode object created."); } } this->SetDoCommandMode(this->last_mode, this->last_instance); }
/* static */ void ScriptController::Sleep(int ticks) { if (!ScriptObject::CanSuspend()) { throw Script_FatalError("You are not allowed to call Sleep in your constructor, Save(), Load(), and any valuator."); } if (ticks <= 0) { ScriptLog::Warning("Sleep() value should be > 0. Assuming value 1."); ticks = 1; } throw Script_Suspend(ticks, NULL); }
/* static */ bool ScriptObject::DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint cmd, const char *text, Script_SuspendCallbackProc *callback) { if (!ScriptObject::CanSuspend()) { throw Script_FatalError("You are not allowed to execute any DoCommand (even indirect) in your constructor, Save(), Load(), and any valuator."); } if (ScriptObject::GetCompany() != OWNER_DEITY && !::Company::IsValidID(ScriptObject::GetCompany())) { ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_INVALID_COMPANY); return false; } assert(StrEmpty(text) || (GetCommandFlags(cmd) & CMD_STR_CTRL) != 0 || StrValid(text, text + strlen(text))); /* Set the default callback to return a true/false result of the DoCommand */ if (callback == NULL) callback = &ScriptInstance::DoCommandReturn; /* Are we only interested in the estimate costs? */ bool estimate_only = GetDoCommandMode() != NULL && !GetDoCommandMode()(); #ifdef ENABLE_NETWORK /* Only set p2 when the command does not come from the network. */ if (GetCommandFlags(cmd) & CMD_CLIENT_ID && p2 == 0) p2 = UINT32_MAX; #endif /* Try to perform the command. */ CommandCost res = ::DoCommandPInternal(tile, p1, p2, cmd, (_networking && !_generating_world) ? ScriptObject::GetActiveInstance()->GetDoCommandCallback() : NULL, text, false, estimate_only); /* We failed; set the error and bail out */ if (res.Failed()) { SetLastError(ScriptError::StringToError(res.GetErrorMessage())); return false; } /* No error, then clear it. */ SetLastError(ScriptError::ERR_NONE); /* Estimates, update the cost for the estimate and be done */ if (estimate_only) { IncreaseDoCommandCosts(res.GetCost()); return true; } /* Costs of this operation. */ SetLastCost(res.GetCost()); SetLastCommandRes(true); if (_generating_world) { IncreaseDoCommandCosts(res.GetCost()); if (callback != NULL) { /* Insert return value into to stack and throw a control code that * the return value in the stack should be used. */ callback(GetActiveInstance()); throw SQInteger(1); } return true; } else if (_networking) { /* Suspend the script till the command is really executed. */ throw Script_Suspend(-(int)GetDoCommandDelay(), callback); } else { IncreaseDoCommandCosts(res.GetCost()); /* Suspend the script player for 1+ ticks, so it simulates multiplayer. This * both avoids confusion when a developer launched his script in a * multiplayer game, but also gives time for the GUI and human player * to interact with the game. */ throw Script_Suspend(GetDoCommandDelay(), callback); } NOT_REACHED(); }