/** * @brief Make sure equipment definitions used to generate teams are proper. * @note Check that the sum of all probabilities is smaller or equal to 100 for a weapon type. * @sa INVSH_EquipActor */ static bool INV_EquipmentDefSanityCheck (void) { int i, j; int sum; bool result = true; for (i = 0; i < csi.numEDs; i++) { const equipDef_t *const ed = &csi.eds[i]; /* only check definitions used for generating teams */ if (!Q_strstart(ed->id, "alien") && !Q_strstart(ed->id, "phalanx")) continue; /* Check primary */ sum = 0; for (j = 0; j < csi.numODs; j++) { const objDef_t *const obj = INVSH_GetItemByIDX(j); if (obj->weapon && obj->fireTwoHanded && (INV_ItemMatchesFilter(obj, FILTER_S_PRIMARY) || INV_ItemMatchesFilter(obj, FILTER_S_HEAVY))) sum += ed->numItems[j]; } if (sum > 100) { Com_Printf("INV_EquipmentDefSanityCheck: Equipment Def '%s' has a total probability for primary weapons greater than 100\n", ed->id); result = false; } /* Check secondary */ sum = 0; for (j = 0; j < csi.numODs; j++) { const objDef_t *const obj = INVSH_GetItemByIDX(j); if (obj->weapon && obj->reload && !obj->deplete && INV_ItemMatchesFilter(obj, FILTER_S_SECONDARY)) sum += ed->numItems[j]; } if (sum > 100) { Com_Printf("INV_EquipmentDefSanityCheck: Equipment Def '%s' has a total probability for secondary weapons greater than 100\n", ed->id); result = false; } /* Check armour */ sum = 0; for (j = 0; j < csi.numODs; j++) { const objDef_t *const obj = INVSH_GetItemByIDX(j); if (INV_ItemMatchesFilter(obj, FILTER_S_ARMOUR)) sum += ed->numItems[j]; } if (sum > 100) { Com_Printf("INV_EquipmentDefSanityCheck: Equipment Def '%s' has a total probability for armours greater than 100\n", ed->id); result = false; } /* Don't check misc: the total probability can be greater than 100 */ } return result; }
/** * @brief Activate the node. Can be used without the mouse (ie. a button will execute onClick) */ void uiRadioButtonNode::onActivate (uiNode_t* node) { /* no cvar given? */ if (!EXTRADATA(node).cvar || !*(char*)(EXTRADATA(node).cvar)) { Com_Printf("UI_RadioButtonNodeClick: node '%s' doesn't have a valid cvar assigned\n", UI_GetPath(node)); return; } /* its not a cvar! */ /** @todo the parser should already check that the property value is a right cvar */ char const* const cvarName = Q_strstart((char const*)(EXTRADATA(node).cvar), "*cvar:"); if (!cvarName) return; UI_GetReferenceFloat(node, EXTRADATA(node).cvar); /* Is we click on the already selected button, we can continue */ if (UI_RadioButtonNodeIsSelected(node)) return; if (EXTRADATA(node).string == nullptr) { Cvar_SetValue(cvarName, EXTRADATA(node).value); } else { Cvar_Set(cvarName, "%s", EXTRADATA(node).string); } if (node->onChange) { UI_ExecuteEventActions(node, node->onChange); } if (node->lua_onChange != LUA_NOREF) { UI_ExecuteLuaEventScript(node, node->lua_onChange); } }
/** * @brief Activate the node. Can be used without the mouse (ie. a button will execute onClick) */ static void UI_CheckBoxNodeActivate (uiNode_t *node) { const float last = UI_GetReferenceFloat(node, EXTRADATA(node).value); float value; if (node->disabled) return; /* update value */ value = (last > 0) ? 0 : 1; if (last == value) return; /* save result */ EXTRADATA(node).lastdiff = value - last; if (Q_strstart((const char *)EXTRADATA(node).value, "*cvar:")) { Cvar_SetValue(&((const char*)EXTRADATA(node).value)[6], value); } else { *(float*) EXTRADATA(node).value = value; } /* fire change event */ if (node->onChange) { UI_ExecuteEventActions(node, node->onChange); } }
/** * @brief Called when we press a key when the node got the focus * @return True, if we use the event */ static qboolean UI_KeyBindingNodeKeyPressed (uiNode_t *node, unsigned int key, unsigned short unicode) { const char *command; const char *binding; UI_RemoveFocus(); /** @todo what about macro expansion? */ if (!Q_strstart(node->text, "*binding:")) return qfalse; command = node->text + 9; /** @todo ensure that the binding for the key command is not executed */ binding = Key_GetBinding(command, EXTRADATA(node).keySpace); if (binding[0] != '\0') { /* if it's the same command, do not change anything, otherwise * show the reason why nothing was changed */ if (!Q_streq(binding, command)) { const char *keyStr = Key_KeynumToString(key); UI_DisplayNotice(va(_("Key %s already bound"), keyStr), 2000, NULL); } return qfalse; } /* fire change event */ if (node->onChange) UI_ExecuteEventActions(node, node->onChange); Key_SetBinding(key, command, EXTRADATA(node).keySpace); return qtrue; }
void Cmd_PrintDebugCommands (void) { const cmd_function_t *cmd; const char* otherCommands[] = {"mem_stats", "cl_configstrings", "cl_userinfo", "devmap"}; int num = lengthof(otherCommands); Com_Printf("Debug commands:\n"); for (cmd = cmd_functions; cmd; cmd = cmd->next) { if (Q_strstart(cmd->name, "debug_")) Com_Printf(" * %s\n %s\n", cmd->name, cmd->description); } Com_Printf("Other useful commands:\n"); while (num) { const char *desc = Cmd_GetCommandDesc(otherCommands[num - 1]); Com_Printf(" * %s\n %s\n", otherCommands[num - 1], desc); num--; } Com_Printf(" * sv debug_showall\n" " make everything visible to everyone\n" " * sv debug_actorinvlist\n" " Show the whole inv of all actors on the server console\n" ); Com_Printf("\n"); }
/** called when the window is pushed * check cvar then, reduce runtime check * @todo move cvar check to AbstractOption */ static void UI_TabNodeInit (uiNode_t *node, linkedList_t *params) { const char *cvarName; /* no cvar given? */ if (!(EXTRADATA(node).cvar)) return; /* not a cvar? */ if (!Q_strstart(EXTRADATA(node).cvar, "*cvar:")) { /* normalize */ Com_Printf("UI_TabNodeInit: node '%s' doesn't have a valid cvar assigned (\"%s\" read)\n", UI_GetPath(node), EXTRADATA(node).cvar); EXTRADATA(node).cvar = NULL; return; } /* cvar do not exists? */ cvarName = &EXTRADATA(node).cvar[6]; if (Cvar_FindVar(cvarName) == NULL) { /* search default value, if possible */ uiNode_t* option = node->firstChild; assert(option->behaviour == ui_optionBehaviour); Cvar_ForceSet(cvarName, OPTIONEXTRADATA(option).value); } }
/** * Apply an action value to a node property. If the tuple property/value allow it, the function * pre compute the value and update the action value to speed up the next call. * @param node Node to edit * @param property Property of the node to edit * @param value Action value containing the value to set to the node property * @param context Call context of the script * @todo refactoring it to remove "context", we should only call that function when the action * value is a leaf (then a value, and not an expression) */ static void UI_NodeSetPropertyFromActionValue (uiNode_t *node, const value_t *property, const uiCallContext_t *context, uiAction_t* value) { /* @todo we can use a new EA_VALUE type to flag already parsed values, we dont need to do it again and again */ /* pre compute value if possible */ if (value->type == EA_VALUE_STRING) { const char* string = value->d.terminal.d1.constString; if ((property->type & V_UI_MASK) == V_UI_CVAR && Q_strstart(string, "*cvar:")) { Com_GetValue<void*>(node, property) = value->d.terminal.d1.data; } else { /** @todo here we must catch error in a better way, and using cvar for error code to create unittest automations */ UI_InitRawActionValue(value, node, property, string); } } /* decode RAW value */ if (value->type == EA_VALUE_RAW) { const void *rawValue = value->d.terminal.d1.constData; const int rawType = value->d.terminal.d2.integer; UI_NodeSetPropertyFromRAW(node, property, rawValue, rawType); } /* else it is an expression */ else { /** @todo we should improve if when the prop is a boolean/int/float */ const char* string = UI_GetStringFromExpression(value, context); UI_NodeSetProperty(node, property, string); } }
/** * @sa Com_MacroExpandString * @todo we should review this code, '*' doesn't work very well for all the needed things */ const char *UI_GetReferenceString (const uiNode_t* const node, const char *ref) { if (!ref) return nullptr; /* its a cvar */ if (ref[0] != '*') return CL_Translate(ref); /* get the reference and the name */ const char *token = Com_MacroExpandString(ref); if (token) return CL_Translate(token); /* skip the star */ token = ref + 1; if (token[0] == '\0') return nullptr; if (char const* const binding = Q_strstart(token, "binding:")) { return Key_GetBinding(binding, cls.state != ca_active ? KEYSPACE_UI : KEYSPACE_GAME); } Sys_Error("UI_GetReferenceString: unknown reference %s", token); }
/** * Ask the current selected solider to execute an action * @todo extend it to open doors, or thing like that */ static void HUD_ExecuteAction_f (void) { if (!selActor) return; if (Cmd_Argc() < 2) { Com_Printf("Usage: %s <actionid>\n", Cmd_Argv(0)); return; } if (Q_streq(Cmd_Argv(1), "reload_handl")) { HUD_ReloadLeft_f(); return; } if (Q_streq(Cmd_Argv(1), "reload_handr")) { HUD_ReloadRight_f(); return; } if (Q_strstart(Cmd_Argv(1), "fire_hand") && strlen(Cmd_Argv(1)) >= 13) { const char hand = Cmd_Argv(1)[9]; const int index = atoi(Cmd_Argv(1) + 12); Cmd_ExecuteString(va("hud_fireweapon %c %i", hand, index)); return; } Com_Printf("HUD_ExecuteAction_f: Action \"%s\" unknown.\n", Cmd_Argv(1)); }
/** * @brief Return a float from a node property * @param[in] node Requested node * @param[in] property Requested property * @return Return the float value of a property, else 0, if the type is not supported * @note If the type is not supported, a waring is reported to the console */ float UI_GetFloatFromNodeProperty (const uiNode_t* node, const value_t* property) { assert(node); if (property->type == V_FLOAT) { return Com_GetValue<float>(node, property); } else if ((property->type & V_UI_MASK) == V_UI_CVAR) { void* const b = Com_GetValue<void*>(node, property); if (char const* const cvarName = Q_strstart((char const*)b, "*cvar:")) { const cvar_t* cvar = Cvar_Get(cvarName, "", 0, "UI script cvar property"); return cvar->value; } else if (property->type == V_CVAR_OR_FLOAT) { return *(const float*) b; } else if (property->type == V_CVAR_OR_STRING) { return atof((const char*)b); } } else if (property->type == V_INT) { return Com_GetValue<int>(node, property); } else if (property->type == V_BOOL) { return Com_GetValue<bool>(node, property); } else { #ifdef DEBUG Com_Printf("UI_GetFloatFromNodeProperty: Unimplemented float getter for property '%s@%s'. If it should return a float, request it.\n", UI_GetPath(node), property->string); #else Com_Printf("UI_GetFloatFromNodeProperty: Property '%s@%s' can't return a float\n", UI_GetPath(node), property->string); #endif } return 0; }
/** * @brief Activate the node. Can be used without the mouse (ie. a button will execute onClick) */ static void UI_RadioButtonNodeActivate (uiNode_t * node) { /* no cvar given? */ if (!EXTRADATA(node).cvar || !*(char*)(EXTRADATA(node).cvar)) { Com_Printf("UI_RadioButtonNodeClick: node '%s' doesn't have a valid cvar assigned\n", UI_GetPath(node)); return; } /* its not a cvar! */ /** @todo the parser should already check that the property value is a right cvar */ if (!Q_strstart((const char *)(EXTRADATA(node).cvar), "*cvar")) return; UI_GetReferenceFloat(node, EXTRADATA(node).cvar); /* Is we click on the already selected button, we can continue */ if (UI_RadioButtonNodeIsSelected(node)) return; { const char *cvarName = &((const char *)(EXTRADATA(node).cvar))[6]; if (EXTRADATA(node).string == NULL) { Cvar_SetValue(cvarName, EXTRADATA(node).value); } else { Cvar_Set(cvarName, EXTRADATA(node).string); } if (node->onChange) UI_ExecuteEventActions(node, node->onChange); } }
/** * @brief Get the correct animation for the given actor state and weapons * @param[in] anim Type of animation (for example "stand", "walk") * @param[in] right ods index to determine the weapon in the actors right hand * @param[in] left ods index to determine the weapon in the actors left hand * @param[in] state the actors state - e.g. STATE_CROUCHED (crouched animations) * have a 'c' in front of their animation definitions (see *.anm files for * characters) */ const char* LE_GetAnim (const char* anim, int right, int left, int state) { if (!anim) return ""; static char retAnim[MAX_VAR]; char* mod = retAnim; size_t length = sizeof(retAnim); /* add crouched flag */ if (state & STATE_CROUCHED) { *mod++ = 'c'; length--; } /* determine relevant data */ char animationIndex; char const* type; if (right == NONE) { animationIndex = '0'; if (left == NONE) type = "item"; else { type = INVSH_GetItemByIDX(left)->type; /* left hand grenades look OK with default anim; others don't */ if (!Q_streq(type, "grenade")) { type = "pistol_d"; } } } else { const objDef_t* od = INVSH_GetItemByIDX(right); animationIndex = od->animationIndex; type = od->type; if (left != NONE && Q_streq(od->type, "pistol") && Q_streq(INVSH_GetItemByIDX(left)->type, "pistol")) { type = "pistol_d"; } } if (Q_strstart(anim, "stand") || Q_strstart(anim, "walk")) { Com_sprintf(mod, length, "%s%c", anim, animationIndex); } else { Com_sprintf(mod, length, "%s_%s", anim, type); } return retAnim; }
/** * @brief Checks whether this entity is an inline model that should have brushes * @param[in] entName * @return true if the name of the entity implies, that this is an inline model */ static inline bool IsInlineModelEntity (const char* entName) { const bool inlineModelEntity = (Q_streq("func_breakable", entName) || Q_streq("func_door", entName) || Q_streq("func_door_sliding", entName) || Q_streq("func_rotating", entName) || Q_strstart(entName, "trigger_")); return inlineModelEntity; }
float UI_GetReferenceFloat (const uiNode_t* const node, const void* ref) { if (!ref) return 0.0; if (char const* const token = Q_strstart((char const*)ref, "*")) { if (token[0] == '\0') return 0.0; if (char const* const cvar = Q_strstart(token, "cvar:")) { return Cvar_GetValue(cvar); } Sys_Error("UI_GetReferenceFloat: unknown reference '%s' from node '%s'", token, node->name); } /* just get the data */ return *(const float*) ref; }
static void Test_Parameters (const int argc, char** argv) { int i; for (i = 1; i < argc; i++) { if (char const* const arg = Q_strstart(argv[i], "-D")) { if (char const* const value = strchr(arg, '=')) { char name[32]; size_t const size = value - arg + 1; if (size >= sizeof(name)) { fprintf(stderr, "Error: Argument \"%s\" use a property name too much big.\n", argv[i]); exit(2); } Q_strncpyz(name, arg, size); TEST_RegisterProperty(name, value + 1); } else { fprintf(stderr, "Warning: \"%s\" do not value. Command line argument ignored.\n", argv[i]); } } else if (char const* const prefix = Q_strstart(argv[i], "--output-prefix=")) { resultPrefix = prefix; } else if (Q_streq(argv[i], "--log")) { config.log = true; } else if (Q_streq(argv[i], "--verbose")) { config.verbose = true; } else if (Q_streq(argv[i], "-h") || Q_streq(argv[i], "--help")) { printf("Usage:\n"); printf("-h --help | show this help screen\n"); printf("-Dprop=value | defines a test property\n"); printf(" --log | log ufo output to file (testall.log in working dir)\n"); printf(" --output-prefix=PREFIX | set a prefix for the xml result\n"); printf(" | default value is \"ufoai\"\n"); exit(0); } else { fprintf(stderr, "Error: Param \"%s\" unknown\n", argv[i]); fprintf(stderr, "Use \"%s -h\" to show the help screen\n", argv[0]); exit(2); } } }
const char* CL_Translate (const char* t) { if (t[0] == '_') { if (t[1] != '\0') t = _(++t); } else { const char* msgid = Q_strstart(t, "*msgid:"); if (msgid != nullptr) t = CL_GetMessageID(msgid); } return t; }
const char *UI_AbstractOptionGetCurrentValue (uiNode_t * node) { /* no cvar given? */ if (!EXTRADATA(node).cvar || !*EXTRADATA(node).cvar) { Com_Printf("UI_AbstractOptionGetCurrentValue: node '%s' doesn't have a valid cvar assigned\n", UI_GetPath(node)); return NULL; } /* not a cvar? */ if (!Q_strstart(EXTRADATA(node).cvar, "*cvar:")) return NULL; return UI_GetReferenceString(node, EXTRADATA(node).cvar); }
const char* UI_AbstractOption_GetCurrentValue (uiNode_t* node) { /* no cvar given? */ if (!EXTRADATA(node).cvar || !*EXTRADATA(node).cvar) { Com_Printf("UI_AbstractOptionGetCurrentValue: node [%s] doesn't have a valid cvar assigned\n", UI_GetPath(node)); return nullptr; } /* not a cvar? */ if (!Q_strstart(EXTRADATA(node).cvar, "*cvar:")) { Com_Printf("UI_AbstractOptionGetCurrentValue: in node [%s], the name [%s] is not a value cvar\n", UI_GetPath(node), EXTRADATA(node).cvar); return nullptr; } return UI_GetReferenceString(node, EXTRADATA(node).cvar); }
/** * @brief Called when the user click with the right mouse button */ static void UI_KeyBindingNodeClick (uiNode_t *node, int x, int y) { if (node->disabled) return; /* no binding given */ if (!node->text) return; if (!Q_strstart(node->text, "*binding")) return; if (!UI_HasFocus(node)) { if (node->onClick) UI_ExecuteEventActions(node, node->onClick); UI_RequestFocus(node); } }
/** * @brief Called when the user click with the right mouse button */ static void UI_TextEntryNodeClick (uiNode_t *node, int x, int y) { if (node->disabled) return; /* no cvar */ if (!node->text) return; if (!Q_strstart(node->text, "*cvar")) return; if (!UI_HasFocus(node)) { if (node->onClick) { UI_ExecuteEventActions(node, node->onClick); } UI_RequestFocus(node); } }
/** * @brief Called when the user click with the right mouse button */ void uiTextEntryNode::onLeftClick (uiNode_t* node, int x, int y) { if (node->disabled) return; /* no cvar */ if (!node->text) return; if (!Q_strstart(node->text, "*cvar:")) return; if (!UI_HasFocus(node)) { if (node->onClick) { UI_ExecuteEventActions(node, node->onClick); } if (node->lua_onClick != LUA_NOREF) { UI_ExecuteLuaEventScript_XY(node, node->lua_onClick, x, y); } UI_RequestFocus(node); } }
/** * @brief after execution of a unittest window, it analyse color of * normalized indicator, and create asserts. Both Fail/Pass asserts is * useful to count number. */ static void UFO_AnalyseTestWindow (const char* windowName) { const uiBehaviour_t* stringBehaviour = UI_GetNodeBehaviour("string"); const uiNode_t* node; const uiNode_t* window = UI_GetWindow(windowName); CU_ASSERT_FATAL(window != nullptr); CU_ASSERT_FATAL(stringBehaviour != nullptr); for (node = window->firstChild; node != nullptr; node = node->next) { bool isGreen; bool isRed; /* skip non "string" nodes */ if (node->behaviour != stringBehaviour) continue; if (node->invis) continue; /* skip nodes without "test" prefix */ if (!Q_strstart(node->name, "test")) continue; isGreen = node->color[0] < 0.1 && node->color[1] > 0.9 && node->color[2] < 0.1; isRed = node->color[0] > 0.9 && node->color[1] < 0.1 && node->color[2] < 0.1; if (isGreen) { /** @note Useful to count number of tests */ CU_ASSERT_TRUE(true); } else if (isRed) { const char* message = va("%s.%s failed.", windowName, node->name); /*Com_Printf("Error: %s\n", message);*/ /*CU_FAIL(message);*/ CU_assertImplementation(CU_FALSE, 0, va("CU_FAIL(%s)", message), va("base/ufos/uitest/%s.ufo", windowName), "", CU_FALSE); } else { const char* message = va("%s.%s have an unknown status.", windowName, node->name); /*Com_Printf("Warning: %s\n", message);*/ /*CU_FAIL(message);*/ CU_assertImplementation(CU_FALSE, 0, va("CU_FAIL(%s)", message), va("base/ufos/uitest/%s.ufo", windowName), "", CU_FALSE); } } }
/** * @sa Com_MacroExpandString * @todo we should review this code, '*' doesn't work very well for all the needed things */ const char *UI_GetReferenceString (const uiNode_t* const node, const char *ref) { if (!ref) return NULL; /* its a cvar */ if (ref[0] == '*') { const char *token; /* get the reference and the name */ token = Com_MacroExpandString(ref); if (token) { if (token[0] == '_') { token++; return _(token); } return token; } /* skip the star */ token = ref + 1; if (token[0] == '\0') return NULL; if (char const* const binding = Q_strstart(token, "binding:")) { return Key_GetBinding(binding, cls.state != ca_active ? KEYSPACE_UI : KEYSPACE_GAME); } Sys_Error("UI_GetReferenceString: unknown reference %s", token); /* translatable string */ } else if (ref[0] == '_') { ref++; return _(ref); } /* just a string */ return ref; }
/** called when the window is pushed * check cvar then, reduce runtime check * @todo move cvar check to AbstractOption */ void uiTabNode::onWindowOpened (uiNode_t* node, linkedList_t* params) { /* no cvar given? */ if (!(EXTRADATA(node).cvar)) return; /* not a cvar? */ char const* const cvarName = Q_strstart(EXTRADATA(node).cvar, "*cvar:"); if (!cvarName) { /* normalize */ Com_Printf("UI_TabNodeInit: node '%s' doesn't have a valid cvar assigned (\"%s\" read)\n", UI_GetPath(node), EXTRADATA(node).cvar); EXTRADATA(node).cvar = nullptr; return; } /* cvar does not exist? */ if (Cvar_FindVar(cvarName) == nullptr) { /* search default value, if possible */ uiNode_t* option = node->firstChild; assert(option->behaviour == ui_optionBehaviour); Cvar_ForceSet(cvarName, OPTIONEXTRADATA(option).value); } }
/** * @brief Calculates the size of a container node and links the container * into the node (uses the @c invDef_t shape bitmask to determine the size) * @param[in,out] node The node to get the size for */ void uiContainerNode::onLoaded (uiNode_t* const node) { const char *name; const invDef_t *container; /** @todo find a better way to add more equip node, without this hack */ name = node->name; if (Q_strstart(node->name, "equip_")) name = "equip"; container = INVSH_GetInventoryDefinitionByID(name); if (container == NULL) return; EXTRADATA(node).container = container; if (UI_IsScrollContainerNode(node)) { /* No need to compute the size, the script provide it */ } else { int i, j; /* Start on the last bit of the shape mask. */ for (i = SHAPE_BIG_MAX_WIDTH - 1; i >= 0; i--) { for (j = 0; j < SHAPE_BIG_MAX_HEIGHT; j++) if (container->shape[j] & (1 << i)) break; if (j < SHAPE_BIG_MAX_HEIGHT) break; } node->box.size[0] = C_UNIT * (i + 1) + 0.01; /* start on the lower row of the shape mask */ for (i = SHAPE_BIG_MAX_HEIGHT - 1; i >= 0; i--) if (container->shape[i] & ~0x0) break; node->box.size[1] = C_UNIT * (i + 1) + 0.01; } }
static int CP_CheckTriggerEvent (const char *expression, const void* userdata) { const char *type; /* check that a particular installation type is built already */ type = Q_strstart(expression, "installation"); if (type != 0) { if (strlen(type) <= 1) return -1; char value[MAX_VAR]; Q_strncpyz(value, type + 1, sizeof(value)); value[strlen(value) - 1] = '\0'; const installationType_t insType = INS_GetType(value); if (INS_HasType(insType, INSTALLATION_NOT_USED)) return 1; return 0; } /* check whether a particular ufo was detected */ type = Q_strstart(expression, "ufo"); if (type != 0) { if (strlen(type) <= 1) return -1; char value[MAX_VAR]; Q_strncpyz(value, type + 1, sizeof(value)); value[strlen(value) - 1] = '\0'; const char* detectedUFO = static_cast<const char*>(userdata); if (Q_strnull(detectedUFO)) return -1; return Q_streq(detectedUFO, value); } /* check that the given xvi level is reached in any nation */ type = Q_strstart(expression, "xvi"); if (type != 0) { int xvi; if (sscanf(type, "[%i]", &xvi) != 1) return -1; int i; /* check for XVI infection rate */ for (i = 0; i < ccs.numNations; i++) { const nation_t *nation = NAT_GetNationByIDX(i); const nationInfo_t *stats = NAT_GetCurrentMonthInfo(nation); if (stats->xviInfection >= xvi) return 1; } return 0; } /* check for nation happiness - also see the lost conditions in the campaign */ type = Q_strstart(expression, "nationhappiness"); if (type != 0) { int nationAmount; if (sscanf(type, "[%i]", &nationAmount) != 1) return -1; int j, nationBelowLimit = 0; for (j = 0; j < ccs.numNations; j++) { const nation_t *nation = NAT_GetNationByIDX(j); const nationInfo_t *stats = NAT_GetCurrentMonthInfo(nation); if (stats->happiness < ccs.curCampaign->minhappiness) { nationBelowLimit++; if (nationBelowLimit >= nationAmount) return 1; } } return 0; } /* check that the given average xvi level is reached */ type = Q_strstart(expression, "averagexvi"); if (type != 0) { int xvipercent; if (sscanf(type, "[%i]", &xvipercent) != 1) return -1; if (xvipercent < 0 || xvipercent > 100) return -1; const int xvi = CP_GetAverageXVIRate(); if (xvi > ccs.curCampaign->maxAllowedXVIRateUntilLost * xvipercent / 100) return 1; return 0; } type = Q_strstart(expression, "difficulty"); if (type != 0) { int difficulty; if (sscanf(type, "[%i]", &difficulty) != 1) return -1; return ccs.curCampaign->difficulty == difficulty; } /* check that these days have passed in the campaign */ type = Q_strstart(expression, "days"); if (type != 0) { int days; if (sscanf(type, "[%i]", &days) != 1) return -1; date_t d = ccs.curCampaign->date; d.day += days; if (Date_IsDue(&d)) return 1; return 0; } type = Q_strstart(expression, "alienscaptured"); if (type != 0) { if (ccs.campaignStats.capturedAliens > 0) return 1; return 0; } type = Q_strstart(expression, "samsitearmed"); if (type != 0) { if (!INS_HasType(INSTALLATION_DEFENCE)) return 1; INS_ForeachOfType(installation, INSTALLATION_DEFENCE) { if (installation->installationStatus == INSTALLATION_WORKING) { for (int i = 0; i < installation->installationTemplate->maxBatteries; i++) { const aircraftSlot_t *slot = &installation->batteries[i].slot; if (slot->ammoLeft > 0) return 1; } } } return 0; } return -1; }
TEST_F(RendererTest, CharacterAnimationFiles) { const char* pattern = "models/**.anm"; const char* filename; mAliasModel_t mod; const char* bloodspider[] = { "death1", "death2", "death3", "dead1", "dead2", "dead3", "stand0", "stand1", "stand2", "stand3", "walk0", "walk1", "walk2", "walk3", "cstand0", "cstand1", "cstand2", "cstand3", "cwalk0", "cwalk1", "cwalk2", "cwalk3", "stand_menu", "panic0", nullptr }; const char* hovernet[] = { "death1", "dead1", "death2","dead2", "death3", "dead3", "stand0", "walk0", "cstand0", "cwalk0", "stand1", "walk1", "cstand1", "cwalk1", "stand2", "walk2", "cstand2", "cwalk2", "stand3", "walk3", "cstand3", "cwalk3", "move_rifle", "shoot_rifle", "cmove_rifle", "cshoot_rifle", "stand_menu", "panic0", nullptr }; const char* soldiers[] = { "death1", "death2", "death3", "dead1", "dead2", "dead3", "stand0", "stand1", "stand2", "stand3", "walk0", "walk1", "walk2", "walk3", "cstand0", "cstand1", "cstand2", "cstand3", "cwalk0", "cwalk1", "cwalk2", "cwalk3", "stand_menu", "panic0", "move_rifle", "shoot_rifle", "cmove_rifle", "cshoot_rifle", "move_biggun", "shoot_biggun", "cmove_biggun", "cshoot_biggun", "move_melee", "shoot_melee", "cmove_melee", "cshoot_melee", "stand_still", "move_pistol", "shoot_pistol", "cmove_pistol", "cshoot_pistol", "move_pistol_d", "shoot_pistol_d", "cmove_pistol_d", "cshoot_pistol_d", "move_grenade", "shoot_grenade", "cmove_grenade", "cshoot_grenade", "move_item", "shoot_item", "cmove_item", "cshoot_item", "move_rpg", "shoot_rpg", "cmove_rpg", "cshoot_rpg", nullptr }; const char* civilians[] = { "death1", "dead1", "death2", "dead2", "death3", "dead3", "stand0", "walk0", "panic0", "stand1", "stand2", "stand_menu", "stand_still", nullptr }; FS_BuildFileList(pattern); vid_modelPool = Mem_CreatePool("Vid Model Pool"); while ((filename = FS_NextFileFromFileList(pattern)) != nullptr) { const char** animList; if (Q_strstart(filename, "models/soldiers/")) animList = soldiers; else if (Q_strstart(filename, "models/civilians/")) animList = civilians; else if (Q_strstart(filename, "models/aliens/bloodspider")) animList = bloodspider; else if (Q_strstart(filename, "models/aliens/hovernet")) animList = hovernet; else if (Q_strstart(filename, "models/aliens/")) animList = soldiers; else animList = nullptr; /** @todo remove this hack - but ugvs are just not ready yet */ if (Q_strstart(filename, "models/soldiers/ugv_")) continue; /** @todo remove this hack - alientank is just not ready yet */ if (Q_strstart(filename, "models/aliens/alientank/")) continue; if (animList != nullptr) { OBJZERO(mod); /* set a very high value to work around the error check in the loading function */ mod.num_frames = 100000; Com_Printf("load character anim file: %s\n", filename); R_ModLoadAnims(&mod, filename); while (*animList != nullptr) { int i; for (i = 0; i < mod.num_anims; i++) { const mAliasAnim_t* a = &mod.animdata[i]; if (Q_streq(a->name, *animList)) break; } ASSERT_FALSE(i == mod.num_anims) << "anm file " << filename << " does not contain the needed animation definition " << *animList; animList++; } } } Mem_DeletePool(vid_modelPool); FS_NextFileFromFileList(nullptr); }
/** * @brief Change the server to a new map, taking all connected clients along with it. * @note the full syntax is: @code map [day|night] [+]<map> [<assembly>] @endcode * @sa SV_AssembleMap * @sa CM_LoadMap * @sa Com_SetServerState */ void SV_Map (qboolean day, const char *levelstring, const char *assembly) { int i; unsigned checksum = 0; char * map = SV_GetConfigString(CS_TILES); char * pos = SV_GetConfigString(CS_POSITIONS); mapInfo_t *randomMap = NULL; client_t *cl; /* any partially connected client will be restarted */ Com_SetServerState(ss_restart); /* the game is just starting */ SV_InitGame(); if (!svs.initialized) { Com_Printf("Could not spawn the server\n"); return; } assert(levelstring[0] != '\0'); Com_DPrintf(DEBUG_SERVER, "SpawnServer: %s\n", levelstring); /* save name for levels that don't set message */ SV_SetConfigString(CS_NAME, levelstring); SV_SetConfigString(CS_LIGHTMAP, day); Q_strncpyz(sv->name, levelstring, sizeof(sv->name)); /* set serverinfo variable */ sv_mapname = Cvar_FullSet("sv_mapname", sv->name, CVAR_SERVERINFO | CVAR_NOSET); /* notify the client in case of a listening server */ SCR_BeginLoadingPlaque(); if (assembly) Q_strncpyz(sv->assembly, assembly, sizeof(sv->assembly)); else sv->assembly[0] = '\0'; /* leave slots at start for clients only */ cl = NULL; while ((cl = SV_GetNextClient(cl)) != NULL) { /* needs to reconnect */ if (cl->state >= cs_spawning) SV_SetClientState(cl, cs_connected); } /* assemble and load the map */ if (levelstring[0] == '+') { randomMap = SV_AssembleMap(levelstring + 1, assembly, map, pos, 0); if (!randomMap) { Com_Printf("Could not load assembly for map '%s'\n", levelstring); return; } } else { SV_SetConfigString(CS_TILES, levelstring); SV_SetConfigString(CS_POSITIONS, assembly ? assembly : ""); } CM_LoadMap(map, day, pos, &sv->mapData, &sv->mapTiles); Com_Printf("checksum for the map '%s': %u\n", levelstring, sv->mapData.mapChecksum); SV_SetConfigString(CS_MAPCHECKSUM, sv->mapData.mapChecksum); checksum = Com_GetScriptChecksum(); Com_Printf("ufo script checksum %u\n", checksum); SV_SetConfigString(CS_UFOCHECKSUM, checksum); SV_SetConfigString(CS_OBJECTAMOUNT, csi.numODs); SV_SetConfigString(CS_VERSION, UFO_VERSION); SV_SetConfigString(CS_MAPTITLE, SV_GetMapTitle(randomMap, levelstring)); if (Q_strstart(SV_GetConfigString(CS_MAPTITLE), "b/")) { /* For base attack, CS_MAPTITLE contains too many chars */ SV_SetConfigString(CS_MAPTITLE, "Base attack"); SV_SetConfigString(CS_NAME, ".baseattack"); } /* clear random-map assembly data */ Mem_Free(randomMap); randomMap = NULL; /* clear physics interaction links */ SV_ClearWorld(); /* fix this! */ for (i = 1; i <= sv->mapData.numInline; i++) sv->models[i] = CM_InlineModel(&sv->mapTiles, va("*%i", i)); /* precache and static commands can be issued during map initialization */ Com_SetServerState(ss_loading); TH_MutexLock(svs.serverMutex); /* load and spawn all other entities */ svs.ge->SpawnEntities(sv->name, SV_GetConfigStringInteger(CS_LIGHTMAP), sv->mapData.mapEntityString); TH_MutexUnlock(svs.serverMutex); /* all precaches are complete */ Com_SetServerState(ss_game); Com_Printf("-------------------------------------\n"); Cbuf_CopyToDefer(); }
/** * @brief Replace injection identifiers (e.g. <eventParam>) by a value * @note The injection identifier can be every node value - e.g. <image> or <width>. * It's also possible to do something like * @code * cmd "set someCvar <min>/<max>" * @endcode */ const char* UI_GenInjectedString (const char* input, bool addNewLine, const uiCallContext_t *context) { static char cmd[256]; int length = sizeof(cmd) - (addNewLine ? 2 : 1); static char propertyName[256]; const char *cin = input; char *cout = cmd; while (length && cin[0] != '\0') { if (cin[0] == '<') { /* read propertyName between '<' and '>' */ const char *next = UI_GenCommandReadProperty(cin, propertyName, sizeof(propertyName)); if (next) { /* cvar injection */ if (char const* const rest = Q_strstart(propertyName, "cvar:")) { cvar_t const* const cvar = Cvar_Get(rest); const int l = snprintf(cout, length, "%s", cvar->string); cout += l; cin = next; length -= l; continue; } else if (char const* const path = Q_strstart(propertyName, "node:")) { uiNode_t *node; const value_t *property; const char* string; int l; UI_ReadNodePath(path, context->source, &node, &property); if (!node) { Com_Printf("UI_GenInjectedString: Node '%s' wasn't found; '' returned\n", path); #ifdef DEBUG Com_Printf("UI_GenInjectedString: Path relative to '%s'\n", UI_GetPath(context->source)); #endif string = ""; } else if (!property) { Com_Printf("UI_GenInjectedString: Property '%s' wasn't found; '' returned\n", path); string = ""; } else { string = UI_GetStringFromNodeProperty(node, property); if (string == NULL) { Com_Printf("UI_GenInjectedString: String getter for '%s' property do not exists; '' injected\n", path); string = ""; } } l = snprintf(cout, length, "%s", string); cout += l; cin = next; length -= l; continue; /* source path injection */ } else if (char const* const command = Q_strstart(propertyName, "path:")) { if (context->source) { const uiNode_t *node = NULL; if (Q_streq(command, "root")) node = context->source->root; else if (Q_streq(command, "this")) node = context->source; else if (Q_streq(command, "parent")) node = context->source->parent; else Com_Printf("UI_GenCommand: Command '%s' for path injection unknown\n", command); if (node) { const int l = snprintf(cout, length, "%s", UI_GetPath(node)); cout += l; cin = next; length -= l; continue; } } /* no prefix */ } else { /* source property injection */ if (context->source) { /* find property definition */ const value_t *property = UI_GetPropertyFromBehaviour(context->source->behaviour, propertyName); if (property) { const char* value; int l; /* inject the property value */ value = UI_GetStringFromNodeProperty(context->source, property); if (value == NULL) value = ""; l = snprintf(cout, length, "%s", value); cout += l; cin = next; length -= l; continue; } } /* param injection */ if (UI_GetParamNumber(context) != 0) { int arg; const int checked = sscanf(propertyName, "%d", &arg); if (checked == 1 && arg >= 1 && arg <= UI_GetParamNumber(context)) { const int l = snprintf(cout, length, "%s", UI_GetParam(context, arg)); cout += l; cin = next; length -= l; continue; } } } } } *cout++ = *cin++; length--; } /* is buffer too small? */ assert(cin[0] == '\0'); if (addNewLine) *cout++ = '\n'; *cout++ = '\0'; /* copy the result into a free va slot */ return va("%s", cmd); }
/** * @brief see if the entity is am actor start point * @note starts with "info_" and contains "_start" * @return true if this is a start point */ static bool Check_IsInfoStart(const char* classname) { return Q_strstart(classname, "info_") && strstr(classname, "_start"); }