Skip to content

Commit

Permalink
qtscript: New function setObjectFlag()
Browse files Browse the repository at this point in the history
Added setObjectFlag(object, flag, value) which allows you to set
a flag on or off for a game object. For now, only the new flag
OBJECT_FLAG_UNSELECTABLE is supported, which will make game
object unable to be selected by the player.

New cheat code 'untouchable' allows you test test this functionality.
  • Loading branch information
perim committed Sep 2, 2017
1 parent 3e52f3d commit 6ea9820
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 7 deletions.
1 change: 1 addition & 0 deletions src/basedef.h
Expand Up @@ -103,6 +103,7 @@ enum OBJECT_FLAG
OBJECT_FLAG_JAMMED_TILES,
OBJECT_FLAG_TARGETED,
OBJECT_FLAG_DIRTY,
OBJECT_FLAG_UNSELECTABLE,
OBJECT_FLAG_COUNT
};

Expand Down
1 change: 1 addition & 0 deletions src/cheat.cpp
Expand Up @@ -47,6 +47,7 @@ static CHEAT_ENTRY cheatCodes[] =
{"jsload", jsAutogame}, // load an AI script for selectedPlayer
{"jsdebug", jsShowDebug}, // show scripting states
{"teach us", kf_TeachSelected}, // give experience to selected units
{"untouchable", kf_Unselectable}, // make selected droids unselectable
{"clone wars", []{ kf_CloneSelected(10); }}, // clone selected units
{"clone wars!", []{ kf_CloneSelected(40); }}, // clone selected units
{"clone wars!!", []{ kf_CloneSelected(135); }}, // clone selected units
Expand Down
4 changes: 2 additions & 2 deletions src/display.cpp
Expand Up @@ -1733,7 +1733,7 @@ static void dealWithLMBStructure(STRUCTURE *psStructure, SELECTION_TYPE selectio
}

/* Got to be built. Also, you can't 'select' derricks */
if (!specialOrderKeyDown() && (psStructure->status == SS_BUILT) &&
if (!specialOrderKeyDown() && (psStructure->status == SS_BUILT) && !psStructure->flags.test(OBJECT_FLAG_UNSELECTABLE) &&
(psStructure->pStructureType->type != REF_RESOURCE_EXTRACTOR) && ownStruct)
{
if (bRightClickOrders)
Expand Down Expand Up @@ -1770,7 +1770,7 @@ static void dealWithLMBStructure(STRUCTURE *psStructure, SELECTION_TYPE selectio
}

}
else if ((psStructure->status == SS_BUILT) &&
else if ((psStructure->status == SS_BUILT) && !psStructure->flags.test(OBJECT_FLAG_UNSELECTABLE) &&
(psStructure->pStructureType->type == REF_RESOURCE_EXTRACTOR) &&
selection == SC_INVALID && ownStruct)
{
Expand Down
4 changes: 4 additions & 0 deletions src/droid.cpp
Expand Up @@ -3136,6 +3136,10 @@ bool checkValidWeaponForProp(DROID_TEMPLATE *psTemplate)
//
void SelectDroid(DROID *psDroid)
{
if (psDroid->flags.test(OBJECT_FLAG_UNSELECTABLE))
{
return;
}
// we shouldn't ever control the transporter in SP games
if (!isTransporter(psDroid) || bMultiPlayer)
{
Expand Down
29 changes: 29 additions & 0 deletions src/keybind.cpp
Expand Up @@ -445,6 +445,35 @@ void kf_TeachSelected()
}
}

void kf_Unselectable()
{
#ifndef DEBUG
// Bail out if we're running a _true_ multiplayer game (to prevent MP cheating)
if (runningMultiplayer())
{
noMPCheatMsg();
return;
}
#endif

for (DROID *psDroid = apsDroidLists[selectedPlayer]; psDroid; psDroid = psDroid->psNext)
{
if (psDroid->selected)
{
psDroid->flags.set(OBJECT_FLAG_UNSELECTABLE, true);
psDroid->selected = false;
}
}
for (STRUCTURE *psStruct = apsStructLists[selectedPlayer]; psStruct; psStruct = psStruct->psNext)
{
if (psStruct->selected)
{
psStruct->flags.set(OBJECT_FLAG_UNSELECTABLE, true);
psStruct->selected = false;
}
}
}

// --------------------------------------------------------------------------
//
///* Prints out the date and time of the build of the game */
Expand Down
1 change: 1 addition & 0 deletions src/keybind.h
Expand Up @@ -235,6 +235,7 @@ void kf_SlowDown();
void kf_NormalSpeed();

void kf_TeachSelected();
void kf_Unselectable();
void kf_CloneSelected(int);
void kf_Reload();

Expand Down
22 changes: 22 additions & 0 deletions src/qtscriptfuncs.cpp
Expand Up @@ -4257,6 +4257,26 @@ static QScriptValue js_setHealth(QScriptContext *context, QScriptEngine *)
return QScriptValue();
}

//-- \subsection{setObjectFlag(object, flag, value)}
//-- Set or unset an object flag on a given game object. Does not take care of network sync, so for multiplayer games,
//-- needs wrapping in a syncRequest. (3.2.4+ only.)
//-- Recognized object flags: OBJECT_FLAG_UNSELECTABLE - makes object unavailable for selection from player UI.
static QScriptValue js_setObjectFlag(QScriptContext *context, QScriptEngine *)
{
QScriptValue obj = context->argument(0);
OBJECT_FLAG flag = (OBJECT_FLAG)context->argument(1).toInt32();
SCRIPT_ASSERT(context, flag < OBJECT_FLAG_COUNT, "Bad flag value %d", context->argument(1).toInt32());
int id = obj.property("id").toInt32();
int player = obj.property("player").toInt32();
OBJECT_TYPE type = (OBJECT_TYPE)obj.property("type").toInt32();
SCRIPT_ASSERT(context, type == OBJ_DROID || type == OBJ_STRUCTURE || type == OBJ_FEATURE, "Bad object type");
BASE_OBJECT *psObj = IdToObject(type, id, player);
SCRIPT_ASSERT(context, psObj, "Object not found!");
bool value = context->argument(2).toBool();
psObj->flags.set(flag, value);
return QScriptValue();
}

//-- \subsection{addSpotter(x, y, player, range, type, expiry)}
//-- Add an invisible viewer at a given position for given player that shows map in given range. \emph{type}
//-- is zero for vision reveal, or one for radar reveal. The difference is that a radar reveal can be obstructed
Expand Down Expand Up @@ -5508,6 +5528,7 @@ bool registerFunctions(QScriptEngine *engine, const QString& scriptName)
engine->globalObject().setProperty("setNoGoArea", engine->newFunction(js_setNoGoArea));
engine->globalObject().setProperty("startTransporterEntry", engine->newFunction(js_startTransporterEntry));
engine->globalObject().setProperty("setTransporterExit", engine->newFunction(js_setTransporterExit));
engine->globalObject().setProperty("setObjectFlag", engine->newFunction(js_setObjectFlag));

// Set some useful constants
engine->globalObject().setProperty("TER_WATER", TER_WATER, QScriptValue::ReadOnly | QScriptValue::Undeletable);
Expand Down Expand Up @@ -5600,6 +5621,7 @@ bool registerFunctions(QScriptEngine *engine, const QString& scriptName)
engine->globalObject().setProperty("PLAYER_DATA", SCRIPT_PLAYER, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("RESEARCH_DATA", SCRIPT_RESEARCH, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("LZ_COMPROMISED_TIME", JS_LZ_COMPROMISED_TIME, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("OBJECT_FLAG_UNSELECTABLE", OBJECT_FLAG_UNSELECTABLE, QScriptValue::ReadOnly | QScriptValue::Undeletable);
// the constants below are subject to change without notice...
engine->globalObject().setProperty("PROX_MSG", MSG_PROXIMITY, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("CAMP_MSG", MSG_CAMPAIGN, QScriptValue::ReadOnly | QScriptValue::Undeletable);
Expand Down
9 changes: 4 additions & 5 deletions src/selection.cpp
Expand Up @@ -58,7 +58,7 @@ static unsigned selSelectUnitsIf(unsigned player, T condition, bool onlyOnScreen
bool shouldSelect = (!onlyOnScreen || droidOnScreen(psDroid, 0)) &&
condition(psDroid);
count += shouldSelect;
if (shouldSelect && !psDroid->selected)
if (shouldSelect && !psDroid->selected && !psDroid->flags.test(OBJECT_FLAG_UNSELECTABLE))
{
SelectDroid(psDroid);
}
Expand Down Expand Up @@ -373,8 +373,7 @@ void selNextSpecifiedBuilding(STRUCTURE_TYPE structType)

for (STRUCTURE *psCurr = apsStructLists[selectedPlayer]; psCurr && !psResult; psCurr = psCurr->psNext)
{
if ((psCurr->pStructureType->type == structType) &&
(psCurr->status == SS_BUILT))
if (psCurr->pStructureType->type == structType && psCurr->status == SS_BUILT)
{
if (!psFirst)
{
Expand Down Expand Up @@ -447,12 +446,12 @@ void selCommander(int n)
{
if (droidIsCommanderNum(psCurr, n))
{
if (!psCurr->selected)
if (!psCurr->selected && !psCurr->flags.test(OBJECT_FLAG_UNSELECTABLE))
{
clearSelection();
psCurr->selected = true;
}
else
else if (!psCurr->flags.test(OBJECT_FLAG_UNSELECTABLE))
{
clearSelection();
psCurr->selected = true;
Expand Down

0 comments on commit 6ea9820

Please sign in to comment.