diff --git a/lib/script/script_parser.y b/lib/script/script_parser.y index 5ffb251c9..a3c51ac6c 100644 --- a/lib/script/script_parser.y +++ b/lib/script/script_parser.y @@ -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); @@ -5388,6 +5398,63 @@ userexp: VAR /* 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 { //ALLOC_BLOCK(psCurrBlock, sizeof(OPCODE) + sizeof(UDWORD)); @@ -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); diff --git a/src/design.c b/src/design.c index 51ad88475..03f88c0e6 100644 --- a/src/design.c +++ b/src/design.c @@ -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 */ diff --git a/src/design.h b/src/design.h index 1f599e48b..9e0dcc4d6 100644 --- a/src/design.h +++ b/src/design.h @@ -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__ diff --git a/src/scriptfuncs.c b/src/scriptfuncs.c index ea2046b4f..6793b6a95 100644 --- a/src/scriptfuncs.c +++ b/src/scriptfuncs.c @@ -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; +} diff --git a/src/scriptfuncs.h b/src/scriptfuncs.h index 8e90a14f0..aadf5ccfa 100644 --- a/src/scriptfuncs.h +++ b/src/scriptfuncs.h @@ -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); diff --git a/src/scriptobj.c b/src/scriptobj.c index df4f7c3dc..4dc988b67 100644 --- a/src/scriptobj.c +++ b/src/scriptobj.c @@ -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) { diff --git a/src/scriptobj.h b/src/scriptobj.h index 60c8e47d2..41b06253a 100644 --- a/src/scriptobj.h +++ b/src/scriptobj.h @@ -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); diff --git a/src/scripttabs.c b/src/scripttabs.c index ec4e3a737..5a8192cc7 100644 --- a/src/scripttabs.c +++ b/src/scripttabs.c @@ -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 }