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"); 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 */ /* Just pass the code up the tree */
/* $1->type = */ /* $1->type = */
$$ = $1; $$ = $1;
@ -5373,6 +5381,8 @@ userexp: VAR
} }
| user_array_var | user_array_var
{ {
RULE("userexp: user_array_var");
codeRet = scriptCodeArrayGet($1, &psCurrBlock); codeRet = scriptCodeArrayGet($1, &psCurrBlock);
CHECK_CODE_ERROR(codeRet); CHECK_CODE_ERROR(codeRet);
@ -5386,6 +5396,63 @@ userexp: VAR
CHECK_CODE_ERROR(codeRet); CHECK_CODE_ERROR(codeRet);
/* Return the code block */ /* 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; $$ = psCurrBlock;
} }
| TRIG_SYM | TRIG_SYM
@ -5562,6 +5629,14 @@ objexp_dot: objexp '.'
{ {
RULE( "objexp_dot: objexp '.', type=%d", $1->type); 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 // Store the object type for the variable lookup
objVarContext = $1->type; objVarContext = $1->type;
} }
@ -5699,6 +5774,8 @@ obj_array_var: OBJ_ARRAY array_index_list
user_array_var: VAR_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); codeRet = scriptCodeArrayVariable($2, $1, &psCurrArrayBlock);
CHECK_CODE_ERROR(codeRet); 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 */ /* Set the shadow bar graphs for the Propulsion stats */
static void intSetPropulsionShadowStats(PROPULSION_STATS *psStats); static void intSetPropulsionShadowStats(PROPULSION_STATS *psStats);
/* Check whether a droid template is valid */ /* 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 */ /* General display window for the design form */
void intDisplayDesignForm(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *pColours); void intDisplayDesignForm(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *pColours);
/* Sets the Design Power Bar for a given Template */ /* 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 */ /* set SHOWTEMPLATENAME to 0 to show template components in edit box */
#define SHOWTEMPLATENAME 0 #define SHOWTEMPLATENAME 0
static const char *GetDefaultTemplateName(DROID_TEMPLATE *psTemplate) const char *GetDefaultTemplateName(DROID_TEMPLATE *psTemplate)
{ {
COMP_BASE_STATS *psStats = NULL; COMP_BASE_STATS *psStats = NULL;
@ -3367,7 +3367,7 @@ static void intSetPropulsionShadowStats(PROPULSION_STATS *psStats)
/* Check whether a droid template is valid */ /* Check whether a droid template is valid */
static BOOL intValidTemplate(DROID_TEMPLATE *psTempl) BOOL intValidTemplate(DROID_TEMPLATE *psTempl, const char *newName)
{ {
UDWORD i; UDWORD i;
@ -3444,8 +3444,8 @@ static BOOL intValidTemplate(DROID_TEMPLATE *psTempl)
//set the droidtype //set the droidtype
psTempl->droidType = droidTemplateType(psTempl); psTempl->droidType = droidTemplateType(psTempl);
/* copy current name into template */ /* copy name into template */
sstrcpy(sCurrDesign.aName, aCurrName); sstrcpy(psTempl->aName, newName);
return true; return true;
} }
@ -3864,7 +3864,7 @@ void intProcessDesign(UDWORD id)
intSetEditBoxTextFromTemplate( &sCurrDesign ); intSetEditBoxTextFromTemplate( &sCurrDesign );
/* flash next button if design not complete */ /* flash next button if design not complete */
if ( intValidTemplate( &sCurrDesign ) == false ) if ( intValidTemplate( &sCurrDesign, aCurrName ) == false )
{ {
/* reset button states */ /* reset button states */
widgSetButtonState(psWScreen, IDDES_SYSTEMBUTTON, 0); widgSetButtonState(psWScreen, IDDES_SYSTEMBUTTON, 0);
@ -4191,7 +4191,7 @@ void intProcessDesign(UDWORD id)
#ifdef FLASH_BUTTONS #ifdef FLASH_BUTTONS
/* lock button if design complete */ /* lock button if design complete */
if ( intValidTemplate( &sCurrDesign ) == true ) if ( intValidTemplate( &sCurrDesign, aCurrName ) == true )
{ {
widgSetButtonState(psWScreen, IDDES_SYSTEMBUTTON, WBUT_CLICKLOCK); widgSetButtonState(psWScreen, IDDES_SYSTEMBUTTON, WBUT_CLICKLOCK);
widgSetButtonState(psWScreen, IDDES_BODYBUTTON, 0); widgSetButtonState(psWScreen, IDDES_BODYBUTTON, 0);
@ -4229,7 +4229,7 @@ void intProcessDesign(UDWORD id)
#ifdef FLASH_BUTTONS #ifdef FLASH_BUTTONS
/* lock button if design complete */ /* lock button if design complete */
if ( intValidTemplate( &sCurrDesign ) == true ) if ( intValidTemplate( &sCurrDesign, aCurrName ) == true )
{ {
widgSetButtonState(psWScreen, IDDES_SYSTEMBUTTON, 0); widgSetButtonState(psWScreen, IDDES_SYSTEMBUTTON, 0);
widgSetButtonState(psWScreen, IDDES_BODYBUTTON, 0); widgSetButtonState(psWScreen, IDDES_BODYBUTTON, 0);
@ -4268,7 +4268,7 @@ void intProcessDesign(UDWORD id)
#ifdef FLASH_BUTTONS #ifdef FLASH_BUTTONS
/* lock button if design complete */ /* lock button if design complete */
if ( intValidTemplate( &sCurrDesign ) == true ) if ( intValidTemplate( &sCurrDesign, aCurrName ) == true )
{ {
//Watermelon:enable the 2nd turret button //Watermelon:enable the 2nd turret button
widgSetButtonState(psWScreen, IDDES_WPBBUTTON, WBUT_CLICKLOCK); widgSetButtonState(psWScreen, IDDES_WPBBUTTON, WBUT_CLICKLOCK);
@ -4291,7 +4291,7 @@ void intProcessDesign(UDWORD id)
#ifdef FLASH_BUTTONS #ifdef FLASH_BUTTONS
/* lock button if design complete */ /* lock button if design complete */
if ( intValidTemplate( &sCurrDesign ) == true ) if ( intValidTemplate( &sCurrDesign, aCurrName ) == true )
{ {
widgSetButtonState(psWScreen, IDDES_SYSTEMBUTTON, 0); widgSetButtonState(psWScreen, IDDES_SYSTEMBUTTON, 0);
widgSetButtonState(psWScreen, IDDES_BODYBUTTON, WBUT_CLICKLOCK); widgSetButtonState(psWScreen, IDDES_BODYBUTTON, WBUT_CLICKLOCK);
@ -4311,7 +4311,7 @@ void intProcessDesign(UDWORD id)
#ifdef FLASH_BUTTONS #ifdef FLASH_BUTTONS
/* lock button if design complete */ /* lock button if design complete */
if ( intValidTemplate( &sCurrDesign ) == true ) if ( intValidTemplate( &sCurrDesign, aCurrName ) == true )
{ {
widgSetButtonState(psWScreen, IDDES_SYSTEMBUTTON, 0); widgSetButtonState(psWScreen, IDDES_SYSTEMBUTTON, 0);
widgSetButtonState(psWScreen, IDDES_BODYBUTTON, 0); widgSetButtonState(psWScreen, IDDES_BODYBUTTON, 0);
@ -4368,7 +4368,7 @@ void intProcessDesign(UDWORD id)
widgReveal( psWScreen, IDDES_STATSFORM ); widgReveal( psWScreen, IDDES_STATSFORM );
/* switch automatically to next component type if initial design */ /* switch automatically to next component type if initial design */
if ( !intValidTemplate( &sCurrDesign ) ) if ( !intValidTemplate( &sCurrDesign, aCurrName ) )
{ {
/* show next component design screen */ /* show next component design screen */
switch ( desCompMode ) 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, /* create new template if button is NULL,
* else store changes to existing template */ * else store changes to existing template */

View File

@ -153,4 +153,8 @@ extern void resetDesignPauseState(void);
extern void reverseTemplateList(DROID_TEMPLATE **ppsList); 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__ #endif // __INCLUDED_SRC_DESIGN_H__

View File

@ -91,6 +91,7 @@
#include "lib/script/chat_processing.h" #include "lib/script/chat_processing.h"
#include "keymap.h" #include "keymap.h"
#include "visibility.h" #include "visibility.h"
#include "design.h"
static INTERP_VAL scrFunctionResult; //function return value to be pushed to stack 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 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 */ /* Check for objects in areas */
@ -11438,3 +11443,312 @@ BOOL scrCheckVisibleTile(void)
return true; 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 scrMoveDroidStopped(void);
extern BOOL scrUpdateVisibleTiles(void); extern BOOL scrUpdateVisibleTiles(void);
extern BOOL scrCheckVisibleTile(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); extern BOOL beingResearchedByAlly(SDWORD resIndex, SDWORD player);

View File

@ -58,7 +58,6 @@ BOOL scrBaseObjGet(UDWORD index)
DROID *psDroid; DROID *psDroid;
STRUCTURE *psStruct; STRUCTURE *psStruct;
FEATURE *psFeature; FEATURE *psFeature;
SDWORD temp;
if (!stackPopParams(1, ST_BASEOBJECT, &psObj)) if (!stackPopParams(1, ST_BASEOBJECT, &psObj))
{ {
@ -314,229 +313,7 @@ BOOL scrBaseObjGet(UDWORD index)
type = (INTERP_TYPE)ST_GROUP; type = (INTERP_TYPE)ST_GROUP;
scrFunctionResult.v.oval = ((DROID *)psObj)->psGroup; scrFunctionResult.v.oval = ((DROID *)psObj)->psGroup;
break; 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: case OBJID_HITPOINTS:
type = VAL_INT; type = VAL_INT;
@ -686,6 +463,89 @@ BOOL scrObjToFeature(void)
// to speed up access // to speed up access
static SDWORD lgX,lgY, lgMembers, lgHealth; 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 // Get values from a group
BOOL scrGroupObjGet(UDWORD index) BOOL scrGroupObjGet(UDWORD index)
{ {

View File

@ -48,14 +48,14 @@ enum _objids
OBJID_SELECTED, // if droid is selected (humans only) OBJID_SELECTED, // if droid is selected (humans only)
OBJID_TARGET, // added object->psTarget OBJID_TARGET, // added object->psTarget
OBJID_GROUP, // group a droid belongs to OBJID_GROUP, // group a droid belongs to
OBJID_WEAP_SHORT_RANGE, // short range of a weapon WEAPID_SHORT_RANGE, // short range of a weapon
OBJID_WEAP_LONG_RANGE, // short range of a weapon WEAPID_LONG_RANGE, // short range of a weapon
OBJID_WEAP_SHORT_HIT, // weapon's chance to hit in the short range WEAPID_SHORT_HIT, // weapon's chance to hit in the short range
OBJID_WEAP_LONG_HIT, // weapon's chance to hit in the long range WEAPID_LONG_HIT, // weapon's chance to hit in the long range
OBJID_WEAP_FIRE_PAUSE, // weapon's fire pause WEAPID_FIRE_PAUSE, // weapon's fire pause
OBJID_WEAP_RELOAD_TIME, // weapon's reload time WEAPID_RELOAD_TIME, // weapon's reload time
OBJID_WEAP_NUM_ROUNDS, // num of weapon's rounds (salvo fire) WEAPID_NUM_ROUNDS, // num of weapon's rounds (salvo fire)
OBJID_WEAP_DAMAGE, // weapon's damage WEAPID_DAMAGE, // weapon's damage
OBJID_HITPOINTS, // doid's health left OBJID_HITPOINTS, // doid's health left
OBJID_ORIG_HITPOINTS, // original health of a droid (when not damaged) OBJID_ORIG_HITPOINTS, // original health of a droid (when not damaged)
}; };
@ -92,6 +92,9 @@ extern BOOL scrObjToFeature(void);
// Get values from a group // Get values from a group
extern BOOL scrGroupObjGet(UDWORD index); extern BOOL scrGroupObjGet(UDWORD index);
// Get values from a weapon
extern BOOL scrWeaponObjGet(UDWORD index);
// default value save routine // default value save routine
extern BOOL scrValDefSave(INTERP_VAL *psVal, char *pBuffer, UDWORD *pSize); 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 }, 3, { VAL_INT, VAL_INT, VAL_INT },
0, 0, NULL, 0, 0, NULL, NULL }, 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 */ /* END new functions */
/* This final entry marks the end of the function list */ /* This final entry marks the end of the function list */
@ -1600,38 +1628,39 @@ VAR_SYMBOL asObjTable[] =
{ "selected", VAL_BOOL, ST_OBJECT, { "selected", VAL_BOOL, ST_OBJECT,
(INTERP_TYPE)ST_DROID, OBJID_SELECTED, scrBaseObjGet, NULL, 0, {0}, NULL }, (INTERP_TYPE)ST_DROID, OBJID_SELECTED, scrBaseObjGet, NULL, 0, {0}, NULL },
/* Weapon Stats */
//weapon short range //weapon short range
{ "shortRange", VAL_INT, ST_OBJECT, { "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 //weapon long range
{ "longRange", VAL_INT, ST_OBJECT, { "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 //weapon short hit chance
{ "shortHit", VAL_INT, ST_OBJECT, { "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 //weapon long hit chance
{ "longHit", VAL_INT, ST_OBJECT, { "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 //weapon damage
{ "damage", VAL_INT, ST_OBJECT, { "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 //weapon fire pause
{ "firePause", VAL_INT, ST_OBJECT, { "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 //weapon reload time
{ "reloadTime", VAL_INT, ST_OBJECT, { "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) //num of weapon's rounds (salvo fire)
{ "numRounds", VAL_INT, ST_OBJECT, { "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 */ /* This entry marks the end of the variable list */
{ NULL, VAL_VOID, (INTERP_TYPE)ST_OBJECT, VAL_VOID, 0, NULL, NULL, 0, {0}, NULL } { NULL, VAL_VOID, (INTERP_TYPE)ST_OBJECT, VAL_VOID, 0, NULL, NULL, 0, {0}, NULL }