Scripting:

-allow creation of unit templates on the fly
-allow direct access to major weapon stats from within scripts

git-svn-id: svn+ssh://svn.gna.org/svn/warzone/trunk@5014 4a71c877-e1ca-e34f-864e-861f7616d084
master
Roman C 2008-05-10 13:20:23 +00:00
parent f5cac3bfc5
commit 3d2dc99003
8 changed files with 546 additions and 252 deletions

View File

@ -3651,6 +3651,14 @@ return_exp: expression
{
RULE( "return_exp: objexp");
/* Just pass the code up the tree */
/* $1->type = */
$$ = $1;
}
| userexp /* templates, bodies etc */
{
RULE( "return_exp: userexp");
/* Just pass the code up the tree */
/* $1->type = */
$$ = $1;
@ -5373,6 +5381,8 @@ userexp: VAR
}
| user_array_var
{
RULE("userexp: user_array_var");
codeRet = scriptCodeArrayGet($1, &psCurrBlock);
CHECK_CODE_ERROR(codeRet);
@ -5386,6 +5396,63 @@ userexp: VAR
CHECK_CODE_ERROR(codeRet);
/* Return the code block */
$$ = psCurrBlock;
}
| USER_FUNC_CUST '(' param_list ')'
{
UDWORD line,paramNumber;
char *pDummy;
if($3->numParams != $1->numParams)
{
debug(LOG_ERROR, "Wrong number of arguments for function call: '%s'. Expected %d parameters instead of %d.", $1->pIdent, $1->numParams, $3->numParams);
scr_error("Wrong number of arguments in function call");
return CE_PARSE;
}
if(!$1->bFunction)
{
debug(LOG_ERROR, "'%s' is not a function", $1->pIdent);
scr_error("Can't call an event");
return CE_PARSE;
}
/* check if right parameters were passed */
paramNumber = checkFuncParamTypes($1, $3);
if(paramNumber > 0)
{
debug(LOG_ERROR, "Parameter mismatch in function call: '%s'. Mismatch in parameter %d.", $1->pIdent, paramNumber);
YYABORT;
}
/* Allocate the code block */
ALLOC_BLOCK(psCurrBlock, $3->size + 1 + 1); //Params + Opcode + event index
ALLOC_DEBUG(psCurrBlock, 1);
ip = psCurrBlock->pCode;
if($3->numParams > 0) /* if any parameters declared */
{
/* Copy in the code for the parameters */
PUT_BLOCK(ip, $3);
FREE_PBLOCK($3);
}
/* Store the instruction */
PUT_OPCODE(ip, OP_FUNC);
PUT_EVENT(ip,$1->index); //Put event index
/* Add the debugging information */
if (genDebugInfo)
{
psCurrBlock->psDebug[0].offset = 0;
scriptGetErrorData((SDWORD *)&line, &pDummy);
psCurrBlock->psDebug[0].line = line;
}
/* remember objexp type for further stuff, like myVar = objFunc(); to be able to check type equivalency */
psCurrBlock->type = $1->retType;
$$ = psCurrBlock;
}
| TRIG_SYM
@ -5562,6 +5629,14 @@ objexp_dot: objexp '.'
{
RULE( "objexp_dot: objexp '.', type=%d", $1->type);
// Store the object type for the variable lookup
objVarContext = $1->type;
}
|
userexp '.'
{
RULE( "objexp_dot: userexp '.', type=%d", $1->type);
// Store the object type for the variable lookup
objVarContext = $1->type;
}
@ -5699,6 +5774,8 @@ obj_array_var: OBJ_ARRAY array_index_list
user_array_var: VAR_ARRAY array_index_list
{
RULE("user_array_var: VAR_ARRAY array_index_list");
codeRet = scriptCodeArrayVariable($2, $1, &psCurrArrayBlock);
CHECK_CODE_ERROR(codeRet);

View File

@ -335,7 +335,7 @@ static void intSetPropulsionStats(PROPULSION_STATS *psStats);
/* Set the shadow bar graphs for the Propulsion stats */
static void intSetPropulsionShadowStats(PROPULSION_STATS *psStats);
/* Check whether a droid template is valid */
static BOOL intValidTemplate(DROID_TEMPLATE *psTempl);
BOOL intValidTemplate(DROID_TEMPLATE *psTempl, const char *newName);
/* General display window for the design form */
void intDisplayDesignForm(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *pColours);
/* Sets the Design Power Bar for a given Template */
@ -1331,7 +1331,7 @@ intChooseSystemStats( DROID_TEMPLATE *psTemplate )
/* set SHOWTEMPLATENAME to 0 to show template components in edit box */
#define SHOWTEMPLATENAME 0
static const char *GetDefaultTemplateName(DROID_TEMPLATE *psTemplate)
const char *GetDefaultTemplateName(DROID_TEMPLATE *psTemplate)
{
COMP_BASE_STATS *psStats = NULL;
@ -3367,7 +3367,7 @@ static void intSetPropulsionShadowStats(PROPULSION_STATS *psStats)
/* Check whether a droid template is valid */
static BOOL intValidTemplate(DROID_TEMPLATE *psTempl)
BOOL intValidTemplate(DROID_TEMPLATE *psTempl, const char *newName)
{
UDWORD i;
@ -3444,8 +3444,8 @@ static BOOL intValidTemplate(DROID_TEMPLATE *psTempl)
//set the droidtype
psTempl->droidType = droidTemplateType(psTempl);
/* copy current name into template */
sstrcpy(sCurrDesign.aName, aCurrName);
/* copy name into template */
sstrcpy(psTempl->aName, newName);
return true;
}
@ -3864,7 +3864,7 @@ void intProcessDesign(UDWORD id)
intSetEditBoxTextFromTemplate( &sCurrDesign );
/* flash next button if design not complete */
if ( intValidTemplate( &sCurrDesign ) == false )
if ( intValidTemplate( &sCurrDesign, aCurrName ) == false )
{
/* reset button states */
widgSetButtonState(psWScreen, IDDES_SYSTEMBUTTON, 0);
@ -4191,7 +4191,7 @@ void intProcessDesign(UDWORD id)
#ifdef FLASH_BUTTONS
/* lock button if design complete */
if ( intValidTemplate( &sCurrDesign ) == true )
if ( intValidTemplate( &sCurrDesign, aCurrName ) == true )
{
widgSetButtonState(psWScreen, IDDES_SYSTEMBUTTON, WBUT_CLICKLOCK);
widgSetButtonState(psWScreen, IDDES_BODYBUTTON, 0);
@ -4229,7 +4229,7 @@ void intProcessDesign(UDWORD id)
#ifdef FLASH_BUTTONS
/* lock button if design complete */
if ( intValidTemplate( &sCurrDesign ) == true )
if ( intValidTemplate( &sCurrDesign, aCurrName ) == true )
{
widgSetButtonState(psWScreen, IDDES_SYSTEMBUTTON, 0);
widgSetButtonState(psWScreen, IDDES_BODYBUTTON, 0);
@ -4268,7 +4268,7 @@ void intProcessDesign(UDWORD id)
#ifdef FLASH_BUTTONS
/* lock button if design complete */
if ( intValidTemplate( &sCurrDesign ) == true )
if ( intValidTemplate( &sCurrDesign, aCurrName ) == true )
{
//Watermelon:enable the 2nd turret button
widgSetButtonState(psWScreen, IDDES_WPBBUTTON, WBUT_CLICKLOCK);
@ -4291,7 +4291,7 @@ void intProcessDesign(UDWORD id)
#ifdef FLASH_BUTTONS
/* lock button if design complete */
if ( intValidTemplate( &sCurrDesign ) == true )
if ( intValidTemplate( &sCurrDesign, aCurrName ) == true )
{
widgSetButtonState(psWScreen, IDDES_SYSTEMBUTTON, 0);
widgSetButtonState(psWScreen, IDDES_BODYBUTTON, WBUT_CLICKLOCK);
@ -4311,7 +4311,7 @@ void intProcessDesign(UDWORD id)
#ifdef FLASH_BUTTONS
/* lock button if design complete */
if ( intValidTemplate( &sCurrDesign ) == true )
if ( intValidTemplate( &sCurrDesign, aCurrName ) == true )
{
widgSetButtonState(psWScreen, IDDES_SYSTEMBUTTON, 0);
widgSetButtonState(psWScreen, IDDES_BODYBUTTON, 0);
@ -4368,7 +4368,7 @@ void intProcessDesign(UDWORD id)
widgReveal( psWScreen, IDDES_STATSFORM );
/* switch automatically to next component type if initial design */
if ( !intValidTemplate( &sCurrDesign ) )
if ( !intValidTemplate( &sCurrDesign, aCurrName ) )
{
/* show next component design screen */
switch ( desCompMode )
@ -4668,7 +4668,7 @@ static BOOL saveTemplate(void)
}
}
if ( bTemplateFound == true && intValidTemplate( &sCurrDesign ) )
if ( bTemplateFound == true && intValidTemplate( &sCurrDesign, aCurrName ) )
{
/* create new template if button is NULL,
* else store changes to existing template */

View File

@ -153,4 +153,8 @@ extern void resetDesignPauseState(void);
extern void reverseTemplateList(DROID_TEMPLATE **ppsList);
extern const char *GetDefaultTemplateName(DROID_TEMPLATE *psTemplate);
extern BOOL intValidTemplate(DROID_TEMPLATE *psTempl, const char *newName);
#endif // __INCLUDED_SRC_DESIGN_H__

View File

@ -91,6 +91,7 @@
#include "lib/script/chat_processing.h"
#include "keymap.h"
#include "visibility.h"
#include "design.h"
static INTERP_VAL scrFunctionResult; //function return value to be pushed to stack
@ -102,6 +103,10 @@ static char strParam1[MAXSTRLEN], strParam2[MAXSTRLEN]; //these should be used
static BOOL structHasModule(STRUCTURE *psStruct);
static DROID_TEMPLATE* scrCheckTemplateExists(SDWORD player, DROID_TEMPLATE *psTempl);
extern UDWORD objID; // unique ID creation thing..
/******************************************************************************************/
/* Check for objects in areas */
@ -11438,3 +11443,312 @@ BOOL scrCheckVisibleTile(void)
return true;
}
/* Assembles a template from components and returns it */
BOOL scrAssembleWeaponTemplate(void)
{
SDWORD player,bodyIndex,weapIndex,propIndex;
DROID_TEMPLATE *pNewTemplate = NULL;
if (!stackPopParams(4, VAL_INT, &player, ST_BODY, &bodyIndex,
ST_PROPULSION, &propIndex, ST_WEAPON, &weapIndex))
{
return false;
}
pNewTemplate = malloc(sizeof(DROID_TEMPLATE));
if (pNewTemplate == NULL)
{
debug(LOG_ERROR, "pNewTemplate: Out of memory");
return false;
}
memset(pNewTemplate, 0, sizeof(DROID_TEMPLATE));
// set template body
pNewTemplate->asParts[COMP_BODY] = bodyIndex;
// set template propulsion
pNewTemplate->asParts[COMP_PROPULSION] = propIndex;
// set template weapon (only one)
pNewTemplate->asParts[COMP_WEAPON] = weapIndex;
pNewTemplate->asWeaps[0] = weapIndex;
pNewTemplate->numWeaps = 1;
// set default components
pNewTemplate->asParts[COMP_SENSOR] = 0;
pNewTemplate->asParts[COMP_ECM] = 0;
pNewTemplate->asParts[COMP_CONSTRUCT] = 0;
pNewTemplate->asParts[COMP_REPAIRUNIT] = 0;
pNewTemplate->asParts[COMP_BRAIN] = 0;
// set droid type
pNewTemplate->droidType = DROID_WEAPON;
// finalize template and set its name
if(!intValidTemplate(pNewTemplate, GetDefaultTemplateName(pNewTemplate)))
{
return false;
}
// make sure we have a valid weapon
if(!checkValidWeaponForProp(pNewTemplate))
{
scrFunctionResult.v.oval = NULL; // failure
}
else
{
DROID_TEMPLATE *tempTemplate = NULL;
// check if an identical template already exists for this player
tempTemplate = scrCheckTemplateExists(player, pNewTemplate);
if(tempTemplate == NULL)
{
// set template id
pNewTemplate->multiPlayerID = (objID<<3)|player;
objID++;
// add template to player template list
pNewTemplate->psNext = apsDroidTemplates[player];
apsDroidTemplates[player] = pNewTemplate; //apsTemplateList?
if (bMultiPlayer)
{
sendTemplate(pNewTemplate);
}
}
else
{
// free resources
free(pNewTemplate);
// already exists, so return it
pNewTemplate = tempTemplate;
}
scrFunctionResult.v.oval = pNewTemplate; // succes
}
// return template to scripts
if (!stackPushResult(ST_TEMPLATE, &scrFunctionResult))
{
return false;
}
return true;
}
/* Checks if template already exists, returns it if yes */
static DROID_TEMPLATE* scrCheckTemplateExists(SDWORD player, DROID_TEMPLATE *psTempl)
{
DROID_TEMPLATE *psCurrent;
UDWORD compType,weaponSlot;
bool bEqual = true;
psCurrent = apsDroidTemplates[player];
while(psCurrent != NULL)
{
// compare components
bEqual = true;
for(compType = 0; bEqual && compType < DROID_MAXCOMP; compType++)
{
if(psTempl->asParts[compType] != psCurrent->asParts[compType])
{
bEqual = false;
}
}
// compare weapon count
if(bEqual && (psTempl->numWeaps != psCurrent->numWeaps))
{
bEqual = false;;
}
// compare all weapons separately
for(weaponSlot = 0; bEqual && (weaponSlot < psTempl->numWeaps); weaponSlot++)
{
if(psTempl->asWeaps[weaponSlot] != psCurrent->asWeaps[weaponSlot])
{
bEqual = false;
}
}
// they are equal, so return the current template
if(bEqual)
{
return psCurrent;
}
// try next one
psCurrent = psCurrent->psNext;
}
return NULL;
}
BOOL scrWeaponShortHitUpgrade(void)
{
SDWORD player,weapIndex;
const WEAPON_STATS *psWeapStats;
if (!stackPopParams(2, VAL_INT, &player, ST_WEAPON, &weapIndex))
{
return false;
}
psWeapStats = &asWeaponStats[weapIndex];
scrFunctionResult.v.ival = asWeaponUpgrade[player][psWeapStats->weaponSubClass].shortHit;
if (!stackPushResult(VAL_INT, &scrFunctionResult))
{
return false;
}
return true;
}
BOOL scrWeaponLongHitUpgrade(void)
{
SDWORD player,weapIndex;
const WEAPON_STATS *psWeapStats;
if (!stackPopParams(2, VAL_INT, &player, ST_WEAPON, &weapIndex))
{
return false;
}
psWeapStats = &asWeaponStats[weapIndex];
scrFunctionResult.v.ival = asWeaponUpgrade[player][psWeapStats->weaponSubClass].longHit;
if (!stackPushResult(VAL_INT, &scrFunctionResult))
{
return false;
}
return true;
}
BOOL scrWeaponDamageUpgrade(void)
{
SDWORD player,weapIndex;
const WEAPON_STATS *psWeapStats;
if (!stackPopParams(2, VAL_INT, &player, ST_WEAPON, &weapIndex))
{
return false;
}
psWeapStats = &asWeaponStats[weapIndex];
scrFunctionResult.v.ival = asWeaponUpgrade[player][psWeapStats->weaponSubClass].damage;
if (!stackPushResult(VAL_INT, &scrFunctionResult))
{
return false;
}
return true;
}
BOOL scrWeaponFirePauseUpgrade(void)
{
SDWORD player,weapIndex;
const WEAPON_STATS *psWeapStats;
if (!stackPopParams(2, VAL_INT, &player, ST_WEAPON, &weapIndex))
{
return false;
}
psWeapStats = &asWeaponStats[weapIndex];
scrFunctionResult.v.ival = asWeaponUpgrade[player][psWeapStats->weaponSubClass].firePause;
if (!stackPushResult(VAL_INT, &scrFunctionResult))
{
return false;
}
return true;
}
BOOL scrIsComponentAvailable(void)
{
SDWORD player;
BOOL bAvailable = false;
INTERP_VAL sVal;
if (!stackPop(&sVal))
{
return false;
}
if (!stackPopParams(1, VAL_INT, &player))
{
return false;
}
if (player >= MAX_PLAYERS)
{
ASSERT( false, "player number is too high" );
return false;
}
switch (sVal.type)
{
case ST_BODY:
bAvailable = (apCompLists[player][COMP_BODY][sVal.v.ival] == AVAILABLE);
break;
case ST_PROPULSION:
bAvailable = (apCompLists[player][COMP_PROPULSION][sVal.v.ival] == AVAILABLE);
break;
case ST_ECM:
bAvailable = (apCompLists[player][COMP_ECM][sVal.v.ival] == AVAILABLE);
break;
case ST_SENSOR:
bAvailable = (apCompLists[player][COMP_SENSOR][sVal.v.ival] == AVAILABLE);
break;
case ST_CONSTRUCT:
bAvailable = (apCompLists[player][COMP_CONSTRUCT][sVal.v.ival] == AVAILABLE);
break;
case ST_WEAPON:
bAvailable = (apCompLists[player][COMP_WEAPON][sVal.v.ival] == AVAILABLE);
break;
case ST_REPAIR:
bAvailable = (apCompLists[player][COMP_REPAIRUNIT][sVal.v.ival] == AVAILABLE);
break;
case ST_BRAIN:
bAvailable = (apCompLists[player][COMP_BRAIN][sVal.v.ival] == AVAILABLE);
break;
default:
ASSERT( false, "unknown component type" );
return false;
}
scrFunctionResult.v.bval = bAvailable;
if (!stackPushResult(VAL_BOOL, &scrFunctionResult))
{
return false;
}
return true;
}
BOOL scrGetBodySize(void)
{
SDWORD bodyIndex;
if (!stackPopParams(1,ST_BODY, &bodyIndex))
{
return false;
}
scrFunctionResult.v.ival = asBodyStats[bodyIndex].size;
if (!stackPushResult(VAL_INT, &scrFunctionResult))
{
return false;
}
return true;
}

View File

@ -645,6 +645,13 @@ extern BOOL scrGetDroidLevel(void);
extern BOOL scrMoveDroidStopped(void);
extern BOOL scrUpdateVisibleTiles(void);
extern BOOL scrCheckVisibleTile(void);
extern BOOL scrAssembleWeaponTemplate(void);
extern BOOL scrWeaponShortHitUpgrade(void);
extern BOOL scrWeaponLongHitUpgrade(void);
extern BOOL scrWeaponDamageUpgrade(void);
extern BOOL scrWeaponFirePauseUpgrade(void);
extern BOOL scrIsComponentAvailable(void);
extern BOOL scrGetBodySize(void);
extern BOOL beingResearchedByAlly(SDWORD resIndex, SDWORD player);

View File

@ -58,7 +58,6 @@ BOOL scrBaseObjGet(UDWORD index)
DROID *psDroid;
STRUCTURE *psStruct;
FEATURE *psFeature;
SDWORD temp;
if (!stackPopParams(1, ST_BASEOBJECT, &psObj))
{
@ -314,229 +313,7 @@ BOOL scrBaseObjGet(UDWORD index)
type = (INTERP_TYPE)ST_GROUP;
scrFunctionResult.v.oval = ((DROID *)psObj)->psGroup;
break;
case OBJID_WEAP_SHORT_RANGE:
type = VAL_INT;
temp = -1; // in case object has no weapon return -1
if (psObj->type == OBJ_STRUCTURE)
{
if(((STRUCTURE *)psObj)->asWeaps[0].nStat > 0)
{
temp = asWeaponStats[((STRUCTURE *)psObj)->asWeaps[0].nStat].shortRange;
}
}
else if (psObj->type == OBJ_DROID)
{
if(((DROID *)psObj)->asWeaps[0].nStat > 0)
{
temp = asWeaponStats[((DROID *)psObj)->asWeaps[0].nStat].shortRange;
}
}
else
{
debug(LOG_ERROR, "scrBaseObjGet(): shortRange: features don't have weapons");
return false;
}
scrFunctionResult.v.ival = temp;
break;
case OBJID_WEAP_LONG_RANGE:
type = VAL_INT;
temp = -1; // in case object has no weapon return -1
if (psObj->type == OBJ_STRUCTURE)
{
if(((STRUCTURE *)psObj)->asWeaps[0].nStat > 0)
{
temp = asWeaponStats[((STRUCTURE *)psObj)->asWeaps[0].nStat].longRange;
}
}
else if (psObj->type == OBJ_DROID)
{
if(((DROID *)psObj)->asWeaps[0].nStat > 0)
{
temp = asWeaponStats[((DROID *)psObj)->asWeaps[0].nStat].longRange;
}
}
else
{
debug(LOG_ERROR, "scrBaseObjGet(): shortRange: features don't have weapons");
return false;
}
scrFunctionResult.v.ival = temp;
break;
case OBJID_WEAP_SHORT_HIT:
type = VAL_INT;
temp = -1; // in case object has no weapon return -1
if (psObj->type == OBJ_STRUCTURE)
{
if(((STRUCTURE *)psObj)->asWeaps[0].nStat > 0)
{
temp = weaponShortHit(&asWeaponStats[((STRUCTURE *)psObj)->asWeaps[0].nStat], psObj->player);
}
}
else if (psObj->type == OBJ_DROID)
{
if(((DROID *)psObj)->asWeaps[0].nStat > 0)
{
temp = weaponShortHit(&asWeaponStats[((DROID *)psObj)->asWeaps[0].nStat], psObj->player);
}
}
else
{
debug(LOG_ERROR, "scrBaseObjGet(): shortHit: features don't have weapons");
return false;
}
scrFunctionResult.v.ival = temp;
break;
case OBJID_WEAP_LONG_HIT:
type = VAL_INT;
temp = -1; // in case object has no weapon return -1
if (psObj->type == OBJ_STRUCTURE)
{
if(((STRUCTURE *)psObj)->asWeaps[0].nStat > 0)
{
temp = weaponLongHit(&asWeaponStats[((STRUCTURE *)psObj)->asWeaps[0].nStat], psObj->player);
}
}
else if (psObj->type == OBJ_DROID)
{
if(((DROID *)psObj)->asWeaps[0].nStat > 0)
{
temp = weaponLongHit(&asWeaponStats[((DROID *)psObj)->asWeaps[0].nStat], psObj->player);
}
}
else
{
debug(LOG_ERROR, "scrBaseObjGet(): shortHit: features don't have weapons");
return false;
}
scrFunctionResult.v.ival = temp;
break;
case OBJID_WEAP_DAMAGE:
type = VAL_INT;
temp = -1; // in case object has no weapon return -1
if (psObj->type == OBJ_STRUCTURE)
{
if(((STRUCTURE *)psObj)->asWeaps[0].nStat > 0)
{
temp = weaponDamage(&asWeaponStats[((STRUCTURE *)psObj)->asWeaps[0].nStat], psObj->player);
}
}
else if (psObj->type == OBJ_DROID)
{
if(((DROID *)psObj)->asWeaps[0].nStat > 0)
{
temp = weaponDamage(&asWeaponStats[((DROID *)psObj)->asWeaps[0].nStat], psObj->player);
}
}
else
{
debug(LOG_ERROR, "scrBaseObjGet(): shortHit: features don't have weapons");
return false;
}
scrFunctionResult.v.ival = temp;
break;
case OBJID_WEAP_FIRE_PAUSE:
type = VAL_INT;
temp = -1; // in case object has no weapon return -1
if (psObj->type == OBJ_STRUCTURE)
{
if(((STRUCTURE *)psObj)->asWeaps[0].nStat > 0)
{
temp = weaponFirePause(&asWeaponStats[((STRUCTURE *)psObj)->asWeaps[0].nStat], psObj->player);
}
}
else if (psObj->type == OBJ_DROID)
{
if(((DROID *)psObj)->asWeaps[0].nStat > 0)
{
temp = weaponFirePause(&asWeaponStats[((DROID *)psObj)->asWeaps[0].nStat], psObj->player);
}
}
else
{
debug(LOG_ERROR, "scrBaseObjGet(): shortHit: features don't have weapons");
return false;
}
scrFunctionResult.v.ival = temp;
break;
case OBJID_WEAP_RELOAD_TIME:
type = VAL_INT;
temp = -1; // in case object has no weapon return -1
if (psObj->type == OBJ_STRUCTURE)
{
if(((STRUCTURE *)psObj)->asWeaps[0].nStat > 0)
{
temp = asWeaponStats[((STRUCTURE *)psObj)->asWeaps[0].nStat].reloadTime;
}
}
else if (psObj->type == OBJ_DROID)
{
if(((DROID *)psObj)->asWeaps[0].nStat > 0)
{
temp = asWeaponStats[((DROID *)psObj)->asWeaps[0].nStat].reloadTime;
}
}
else
{
debug(LOG_ERROR, "scrBaseObjGet(): shortHit: features don't have weapons");
return false;
}
scrFunctionResult.v.ival = temp;
break;
case OBJID_WEAP_NUM_ROUNDS:
type = VAL_INT;
temp = -1; // in case object has no weapon return -1
if (psObj->type == OBJ_STRUCTURE)
{
if(((STRUCTURE *)psObj)->asWeaps[0].nStat > 0)
{
temp = asWeaponStats[((STRUCTURE *)psObj)->asWeaps[0].nStat].numRounds;
}
}
else if (psObj->type == OBJ_DROID)
{
if(((DROID *)psObj)->asWeaps[0].nStat > 0)
{
temp = asWeaponStats[((DROID *)psObj)->asWeaps[0].nStat].numRounds;
}
}
else
{
debug(LOG_ERROR, "scrBaseObjGet(): shortHit: features don't have weapons");
return false;
}
scrFunctionResult.v.ival = temp;
break;
case OBJID_HITPOINTS:
type = VAL_INT;
@ -686,6 +463,89 @@ BOOL scrObjToFeature(void)
// to speed up access
static SDWORD lgX,lgY, lgMembers, lgHealth;
// Get values from a weapon
BOOL scrWeaponObjGet(UDWORD index)
{
INTERP_TYPE type;
SDWORD weapIndex;
if (!stackPopParams(1, ST_WEAPON, &weapIndex))
{
return false;
}
switch (index)
{
case WEAPID_SHORT_RANGE:
type = VAL_INT;
scrFunctionResult.v.ival = asWeaponStats[weapIndex].shortRange;
break;
case WEAPID_LONG_RANGE:
type = VAL_INT;
scrFunctionResult.v.ival = asWeaponStats[weapIndex].longRange;
break;
case WEAPID_SHORT_HIT:
type = VAL_INT;
scrFunctionResult.v.ival = asWeaponStats[weapIndex].shortHit;
break;
case WEAPID_LONG_HIT:
type = VAL_INT;
scrFunctionResult.v.ival = asWeaponStats[weapIndex].longHit;
break;
case WEAPID_DAMAGE:
type = VAL_INT;
scrFunctionResult.v.ival = asWeaponStats[weapIndex].damage;
break;
case WEAPID_FIRE_PAUSE:
type = VAL_INT;
scrFunctionResult.v.ival = asWeaponStats[weapIndex].firePause;
break;
case WEAPID_RELOAD_TIME:
type = VAL_INT;
scrFunctionResult.v.ival = asWeaponStats[weapIndex].reloadTime;
break;
case WEAPID_NUM_ROUNDS:
type = VAL_INT;
scrFunctionResult.v.ival = asWeaponStats[weapIndex].numRounds;
break;
default:
ASSERT( false, "unknown variable index" );
return false;
break;
}
// Return the value
if (!stackPushResult(type, &scrFunctionResult))
{
return false;
}
return true;
}
// Get values from a group
BOOL scrGroupObjGet(UDWORD index)
{

View File

@ -48,14 +48,14 @@ enum _objids
OBJID_SELECTED, // if droid is selected (humans only)
OBJID_TARGET, // added object->psTarget
OBJID_GROUP, // group a droid belongs to
OBJID_WEAP_SHORT_RANGE, // short range of a weapon
OBJID_WEAP_LONG_RANGE, // short range of a weapon
OBJID_WEAP_SHORT_HIT, // weapon's chance to hit in the short range
OBJID_WEAP_LONG_HIT, // weapon's chance to hit in the long range
OBJID_WEAP_FIRE_PAUSE, // weapon's fire pause
OBJID_WEAP_RELOAD_TIME, // weapon's reload time
OBJID_WEAP_NUM_ROUNDS, // num of weapon's rounds (salvo fire)
OBJID_WEAP_DAMAGE, // weapon's damage
WEAPID_SHORT_RANGE, // short range of a weapon
WEAPID_LONG_RANGE, // short range of a weapon
WEAPID_SHORT_HIT, // weapon's chance to hit in the short range
WEAPID_LONG_HIT, // weapon's chance to hit in the long range
WEAPID_FIRE_PAUSE, // weapon's fire pause
WEAPID_RELOAD_TIME, // weapon's reload time
WEAPID_NUM_ROUNDS, // num of weapon's rounds (salvo fire)
WEAPID_DAMAGE, // weapon's damage
OBJID_HITPOINTS, // doid's health left
OBJID_ORIG_HITPOINTS, // original health of a droid (when not damaged)
};
@ -92,6 +92,9 @@ extern BOOL scrObjToFeature(void);
// Get values from a group
extern BOOL scrGroupObjGet(UDWORD index);
// Get values from a weapon
extern BOOL scrWeaponObjGet(UDWORD index);
// default value save routine
extern BOOL scrValDefSave(INTERP_VAL *psVal, char *pBuffer, UDWORD *pSize);

View File

@ -1430,6 +1430,34 @@ FUNC_SYMBOL asFuncTable[] =
3, { VAL_INT, VAL_INT, VAL_INT },
0, 0, NULL, 0, 0, NULL, NULL },
{ "assembleWeaponTemplate", scrAssembleWeaponTemplate, ST_TEMPLATE,
4, { VAL_INT, (INTERP_TYPE)ST_BODY, (INTERP_TYPE)ST_PROPULSION, (INTERP_TYPE)ST_WEAPON },
0, 0, NULL, 0, 0, NULL, NULL },
{ "weaponShortHitUpgrade", scrWeaponShortHitUpgrade, VAL_INT,
2, { VAL_INT, (INTERP_TYPE)ST_WEAPON },
0, 0, NULL, 0, 0, NULL, NULL },
{ "weaponLongHitUpgrade", scrWeaponLongHitUpgrade, VAL_INT,
2, { VAL_INT, (INTERP_TYPE)ST_WEAPON },
0, 0, NULL, 0, 0, NULL, NULL },
{ "weaponDamageUpgrade", scrWeaponDamageUpgrade, VAL_INT,
2, { VAL_INT, (INTERP_TYPE)ST_WEAPON },
0, 0, NULL, 0, 0, NULL, NULL },
{ "weaponFirePauseUpgrade", scrWeaponFirePauseUpgrade, VAL_INT,
2, { VAL_INT, (INTERP_TYPE)ST_WEAPON },
0, 0, NULL, 0, 0, NULL, NULL },
{ "isComponentAvailable", scrIsComponentAvailable, VAL_BOOL,
2, { VAL_INT, (INTERP_TYPE)ST_COMPONENT },
0, 0, NULL, 0, 0, NULL, NULL },
{ "getBodySize", scrGetBodySize, VAL_INT,
1, { (INTERP_TYPE)ST_BODY },
0, 0, NULL, 0, 0, NULL, NULL },
/* END new functions */
/* This final entry marks the end of the function list */
@ -1600,38 +1628,39 @@ VAR_SYMBOL asObjTable[] =
{ "selected", VAL_BOOL, ST_OBJECT,
(INTERP_TYPE)ST_DROID, OBJID_SELECTED, scrBaseObjGet, NULL, 0, {0}, NULL },
/* Weapon Stats */
//weapon short range
{ "shortRange", VAL_INT, ST_OBJECT,
(INTERP_TYPE)ST_BASEOBJECT, OBJID_WEAP_SHORT_RANGE, scrBaseObjGet, NULL, 0, {0}, NULL },
(INTERP_TYPE)ST_WEAPON, WEAPID_SHORT_RANGE, scrWeaponObjGet, NULL, 0, {0}, NULL },
//weapon long range
{ "longRange", VAL_INT, ST_OBJECT,
(INTERP_TYPE)ST_BASEOBJECT, OBJID_WEAP_LONG_RANGE, scrBaseObjGet, NULL, 0, {0}, NULL },
(INTERP_TYPE)ST_WEAPON, WEAPID_LONG_RANGE, scrWeaponObjGet, NULL, 0, {0}, NULL },
//weapon short hit chance
{ "shortHit", VAL_INT, ST_OBJECT,
(INTERP_TYPE)ST_BASEOBJECT, OBJID_WEAP_SHORT_HIT, scrBaseObjGet, NULL, 0, {0}, NULL },
(INTERP_TYPE)ST_WEAPON, WEAPID_SHORT_HIT, scrWeaponObjGet, NULL, 0, {0}, NULL },
//weapon long hit chance
{ "longHit", VAL_INT, ST_OBJECT,
(INTERP_TYPE)ST_BASEOBJECT, OBJID_WEAP_LONG_HIT, scrBaseObjGet, NULL, 0, {0}, NULL },
(INTERP_TYPE)ST_WEAPON, WEAPID_LONG_HIT, scrWeaponObjGet, NULL, 0, {0}, NULL },
//weapon damage
{ "damage", VAL_INT, ST_OBJECT,
(INTERP_TYPE)ST_BASEOBJECT, OBJID_WEAP_DAMAGE, scrBaseObjGet, NULL, 0, {0}, NULL },
(INTERP_TYPE)ST_WEAPON, WEAPID_DAMAGE, scrWeaponObjGet, NULL, 0, {0}, NULL },
//weapon fire pause
{ "firePause", VAL_INT, ST_OBJECT,
(INTERP_TYPE)ST_BASEOBJECT, OBJID_WEAP_FIRE_PAUSE, scrBaseObjGet, NULL, 0, {0}, NULL },
(INTERP_TYPE)ST_WEAPON, WEAPID_FIRE_PAUSE, scrWeaponObjGet, NULL, 0, {0}, NULL },
//weapon reload time
{ "reloadTime", VAL_INT, ST_OBJECT,
(INTERP_TYPE)ST_BASEOBJECT, OBJID_WEAP_RELOAD_TIME, scrBaseObjGet, NULL, 0, {0}, NULL },
(INTERP_TYPE)ST_WEAPON, WEAPID_RELOAD_TIME, scrWeaponObjGet, NULL, 0, {0}, NULL },
//num of weapon's rounds (salvo fire)
{ "numRounds", VAL_INT, ST_OBJECT,
(INTERP_TYPE)ST_BASEOBJECT, OBJID_WEAP_NUM_ROUNDS, scrBaseObjGet, NULL, 0, {0}, NULL },
(INTERP_TYPE)ST_WEAPON, WEAPID_NUM_ROUNDS, scrWeaponObjGet, NULL, 0, {0}, NULL },
/* This entry marks the end of the variable list */
{ NULL, VAL_VOID, (INTERP_TYPE)ST_OBJECT, VAL_VOID, 0, NULL, NULL, 0, {0}, NULL }