Example #1
0
/**
 * @brief Clears the employees list for loaded and new games
 * @sa CL_ResetSinglePlayerData
 * @sa E_DeleteEmployee
 */
void E_ResetEmployees (void)
{
	int i;

	Com_DPrintf(DEBUG_CLIENT, "E_ResetEmployees: Delete all employees\n");
	for (i = EMPL_SOLDIER; i < MAX_EMPL; i++)
		LIST_Delete(&ccs.employees[i]);
}
Example #2
0
/**
 * @brief Closing operations for installations subsystem
 */
void INS_Shutdown (void)
{
	LIST_Delete(&ccs.installations);
#ifdef DEBUG
	Cmd_RemoveCommand("debug_listinstallation");
	Cmd_RemoveCommand("debug_finishinstallation");
#endif
}
Example #3
0
static void testTeamDefsModelScriptData (void)
{
	int i;
	linkedList_t *armourPaths = NULL;

	for (i = 0; i < csi.numTeamDefs; i++) {
		int j;
		const teamDef_t *teamDef = &csi.teamDef[i];
		if (!teamDef->armour)
			continue;

		for (j = 0; j < csi.numODs; j++) {
			const objDef_t *od = INVSH_GetItemByIDX(j);
			if (!INV_IsArmour(od))
				continue;

			/* not for this team */
			if (!CHRSH_IsArmourUseableForTeam(od, teamDef))
				continue;

			if (!LIST_ContainsString(armourPaths, od->armourPath))
				LIST_AddString(&armourPaths, od->armourPath);
		}

		UFO_CU_ASSERT_TRUE_MSG(!LIST_IsEmpty(armourPaths), va("no armour definitions found for team %s - but armour is set to true",
				teamDef->id));

		LIST_Foreach(armourPaths, char const, armourPath) {
			int l;

			for (l = NAME_NEUTRAL; l < NAME_LAST; l++) {
				/* no models for this gender */
				if (!teamDef->numModels[l])
					continue;

				CU_ASSERT_PTR_NOT_NULL_FATAL(teamDef->models[l]);

				for (linkedList_t const* list = teamDef->models[l]; list; list = list->next) {
					teamDef_t::model_t const& m = *static_cast<teamDef_t::model_t const*>(list->data);

					UFO_CU_ASSERT_TRUE_MSG(TEST_CheckModel(va("%s/%s", m.path, m.body)), va("%s does not exist in models/%s (teamDef: %s)",
							m.body, m.path, teamDef->id));
					UFO_CU_ASSERT_TRUE_MSG(TEST_CheckModel(va("%s%s/%s", m.path, armourPath, m.body)), va("%s does not exist in models/%s%s (teamDef: %s)",
							m.body, m.path, armourPath, teamDef->id));

					UFO_CU_ASSERT_TRUE_MSG(TEST_CheckModel(va("%s/%s", m.path, m.head)), va("%s does not exist in models/%s (teamDef: %s)",
							m.head, m.path, teamDef->id));
					UFO_CU_ASSERT_TRUE_MSG(TEST_CheckModel(va("%s%s/%s", m.path, armourPath, m.head)), va("%s does not exist in models/%s%s (teamDef: %s)",
							m.head, m.path, armourPath, teamDef->id));
				}
			}
		}

		LIST_Delete(&armourPaths);
	}
Example #4
0
/**
 * @brief Display the popup_homebase
 * @param[in] aircraft Pointer to aircraft we want to change homebase.
 * @param[in] alwaysDisplay False if popup should be displayed only if at least one base is available.
 * @return true if popup is displayed.
 */
qboolean CL_DisplayHomebasePopup (aircraft_t *aircraft, qboolean alwaysDisplay)
{
	int homebase;
	int numAvailableBases = 0;
	baseCapacities_t capacity;
	linkedList_t* popupListText = NULL;
	base_t *base;

	assert(aircraft);

	capacity = AIR_GetCapacityByAircraftWeight(aircraft);

	LIST_Delete(&popupListData);

	popupNum = 0;
	homebase = -1;

	base = NULL;
	while ((base = B_GetNext(base)) != NULL) {
		char text[MAX_VAR];
		char const* msg;

		if (base == aircraft->homebase) {
			msg = _("current homebase of aircraft");
			LIST_Add(&popupListData, (byte *)&INVALID_BASE, sizeof(int));
			homebase = popupNum;
		} else {
			msg = AIR_CheckMoveIntoNewHomebase(aircraft, base, capacity);
			if (!msg) {
				msg = _("base can hold aircraft");
				LIST_Add(&popupListData, (byte *)&base->idx, sizeof(int));
				numAvailableBases++;
			} else {
				LIST_Add(&popupListData, (byte *)&INVALID_BASE, sizeof(int));
			}
		}

		Com_sprintf(text, sizeof(text), "%s\t%s", base->name, msg);
		LIST_AddString(&popupListText, text);
		popupNum++;
	}

	if (alwaysDisplay || numAvailableBases > 0) {
		CL_GameTimeStop();
		popupListNode = UI_PopupList(_("Change homebase of aircraft"), _("Base\tStatus"), popupListText, "change_homebase <lineselected>;");
		VectorSet(popupListNode->selectedColor, 0.0, 0.78, 0.0);	/**< Set color for selected entry. */
		popupListNode->selectedColor[3] = 1.0;
		UI_TextNodeSelectLine(popupListNode, homebase);
		MAP_SelectAircraft(aircraft);
		return qtrue;
	}

	return qfalse;
}
Example #5
0
/**
 * @brief Parses music definitions for different situations
 * @note We have lists for geoscape, battlescape, main and aircombat
 */
void M_ParseMusic (const char* name, const char** text)
{
	int i;

	if (Q_streq(name, "geoscape"))
		i = MUSIC_GEOSCAPE;
	else if (Q_streq(name, "battlescape"))
		i = MUSIC_BATTLESCAPE;
	else if (Q_streq(name, "aircombat"))
		i = MUSIC_AIRCOMBAT;
	else if (Q_streq(name, "main"))
		i = MUSIC_MAIN;
	else {
		Com_Printf("M_ParseMusic: Invalid music id '%s'!\n", name);
		linkedList_t* list;
		Com_ParseList(text, &list);
		LIST_Delete(&list);
		return;
	}

	/* get it's body */
	linkedList_t* list;
	if (!Com_ParseList(text, &list)) {
		Com_Error(ERR_DROP, "M_ParseMusic: error while reading music \"%s\"", name);
	}

	for (linkedList_t* element = list; element != nullptr; element = element->next) {
		if (musicArrayLength[i] >= MUSIC_MAX_ENTRIES) {
			Com_Printf("M_ParseMusic: Too many music entries for category: '%s'!\n", name);
			break;
		}
		musicArrays[i][musicArrayLength[i]] = Mem_PoolStrDup((char*)element->data, cl_genericPool, 0);
		musicArrayLength[i]++;
	}

	LIST_Delete(&list);
}
Example #6
0
static void UI_TextNodeGenerateLineSplit (uiNode_t* node)
{
	const char* data;
	int bufferSize = 1024;
	char* buffer = Mem_AllocTypeN(char, bufferSize);

	LIST_Delete(&EXTRADATA(node).lineSplit);

	if (node->text != nullptr)
		data = UI_GetReferenceString(node, node->text);
	else if (EXTRADATA(node).super.dataID != TEXT_NULL) {
		const uiSharedData_t* shared;
		shared = &ui_global.sharedData[EXTRADATA(node).super.dataID];
		switch (shared->type) {
		case UI_SHARED_TEXT:
			data = UI_GetText(EXTRADATA(node).super.dataID);
			break;
		case UI_SHARED_LINKEDLISTTEXT:
			return;
		default:
			return;
		}
	} else
		return;

	data = CL_Translate(data);

	while (data[0] != '\0') {
		const char* next = strchr(data, '\n');
		int lineSize;
		if (next == nullptr)
			lineSize = strlen(data);
		else
			lineSize = next - data;

		if (lineSize + 1 > bufferSize) {
			bufferSize = lineSize + 1;
			Mem_Free(buffer);
			buffer = Mem_AllocTypeN(char, bufferSize);
		}

		Q_strncpyz(buffer, data, lineSize + 1);
		LIST_AddString(&EXTRADATA(node).lineSplit, buffer);

		if (next == nullptr)
			break;
		data = next + 1;
	}
Example #7
0
/**
 * @brief Console function to push a window onto the window stack
 * @sa UI_PushWindow
 */
static void UI_PushWindow_f (void)
{
	linkedList_t *params = NULL;
	int i;

	if (Cmd_Argc() == 0) {
		Com_Printf("Usage: %s <name> <params>\n", Cmd_Argv(0));
		return;
	}

	for (i = 2; i < Cmd_Argc(); i++) {
		LIST_AddString(&params, Cmd_Argv(i));
	}
	UI_PushWindow(Cmd_Argv(1), NULL, params);
	LIST_Delete(&params);
}
Example #8
0
/**
 * @brief unittest to check well formed list
 */
TEST_F(ParserTest, ParserListOk)
{
	const char* string = " (  aaa \n \"bbb\" \t ccc \n \n ) ";
	const char* cursor = string;
	linkedList_t* list;

	ASSERT_TRUE(Com_ParseList(&cursor, &list)) << "List parsing failed";

	ASSERT_EQ(LIST_Count(list), 3);

	ASSERT_STREQ(static_cast<const char*>(list->data), "aaa");
	ASSERT_STREQ(static_cast<const char*>(list->next->data), "bbb");
	ASSERT_STREQ(static_cast<const char*>(list->next->next->data), "ccc");

	LIST_Delete(&list);
}
Example #9
0
/**
 * @brief Set Harvest mission, and go to mission pos.
 * @note Harvesting attack mission -- Stage 1
 * @todo Remove me when CP_XVIMissionGo will be implemented
 * This function should take a location close to an XVI infection point
 * see gameplay proposal on wiki
 */
void CP_HarvestMissionGo (mission_t *mission)
{
	const nation_t *nation;

	mission->stage = STAGE_MISSION_GOTO;

	/* Choose a map */
	if (CP_ChooseMap(mission, NULL)) {
		int counter;
		linkedList_t *nationList = NULL;
		const qboolean nationTest = CP_ChooseNation(mission, &nationList);
		for (counter = 0; counter < MAX_POS_LOOP; counter++) {
			if (!CP_GetRandomPosOnGeoscapeWithParameters(mission->pos, mission->mapDef->terrains, mission->mapDef->cultures, mission->mapDef->populations, nationTest ? nationList : NULL))
				continue;
			if (MAP_PositionCloseToBase(mission->pos))
				continue;
			mission->posAssigned = qtrue;
			break;
		}
		if (counter >= MAX_POS_LOOP) {
			Com_Printf("CP_HarvestMissionGo: Error, could not set position.\n");
			CP_MissionRemove(mission);
			return;
		}
		LIST_Delete(&nationList);
	} else {
		Com_Printf("CP_HarvestMissionGo: No map found, remove mission.\n");
		CP_MissionRemove(mission);
		return;
	}

	nation = MAP_GetNation(mission->pos);
	if (nation) {
		Com_sprintf(mission->location, sizeof(mission->location), "%s", _(nation->name));
	} else {
		Com_sprintf(mission->location, sizeof(mission->location), "%s", _("No nation"));
	}

	if (mission->ufo) {
		CP_MissionDisableTimeLimit(mission);
		UFO_SendToDestination(mission->ufo, mission->pos);
	} else {
		/* Go to next stage on next frame */
		mission->finalDate = ccs.date;
	}
}
Example #10
0
/**
 * @brief Reset a shared data. Type became NONE and value became NULL
 */
void UI_ResetData (int dataId)
{
	assert(dataId < UI_MAX_DATAID);
	assert(dataId >= 0);

	switch (ui_global.sharedData[dataId].type) {
	case UI_SHARED_LINKEDLISTTEXT:
		LIST_Delete(&ui_global.sharedData[dataId].data.linkedListText);
		break;
	case UI_SHARED_OPTION:
		if (_Mem_AllocatedInPool(com_genericPool, ui_global.sharedData[dataId].data.option)) {
			UI_DeleteOption(ui_global.sharedData[dataId].data.option);
		}
		break;
	default:
		break;
	}

	ui_global.sharedData[dataId].type = UI_SHARED_NONE;
	ui_global.sharedData[dataId].data.text = NULL;
	ui_global.sharedData[dataId].versionId++;
}
Example #11
0
/**
 * @brief Return a "hired" ugv-employee pointer of a given ugv-type in a given base.
 * @param[in] base Which base the ugv should be searched in.c
 * @param[in] ugvType What type of robot we want.
 * @return employee_t pointer on success or NULL on error.
 * @sa E_GetUnhiredRobot
 */
employee_t* E_GetHiredRobot (const base_t* const base, const ugv_t *ugvType)
{
	linkedList_t *hiredEmployees = NULL;
	employee_t *employee;

	E_GetHiredEmployees(base, EMPL_ROBOT, &hiredEmployees);

	LIST_Foreach(hiredEmployees, employee_t, employee) {
		if ((employee->ugv == ugvType || !ugvType)	/* If no type was given we return the first ugv we find. */
		 && E_IsInBase(employee, base)) {		/* It has to be in the defined base. */
			assert(E_IsHired(employee));
			break;
		}
	}

	LIST_Delete(&hiredEmployees);

	if (!employee)
		Com_DPrintf(DEBUG_CLIENT, "Could not get unhired ugv/robot.\n");

	return employee;
}
Example #12
0
/**
 * @brief Return a list of hired employees in the given base of a given type
 * @param[in] base Which base the employee should be searched in. If NULL is given employees in all bases will be listed.
 * @param[in] type Which employee type to search for.
 * @param[out] hiredEmployees Linked list of hired employees in the base.
 * @return Number of hired employees in the base that are currently not on a transfer. Or @c -1 in case of an error.
 */
int E_GetHiredEmployees (const base_t* const base, employeeType_t type, linkedList_t **hiredEmployees)
{
	employee_t *employee;

	if (type >= MAX_EMPL) {
		Com_Printf("E_GetHiredEmployees: Unknown EmployeeType: %i\n", type);
		*hiredEmployees = NULL;
		return -1;
	}

	LIST_Delete(hiredEmployees);

	E_Foreach(type, employee) {
		if (!E_IsHired(employee))
			continue;
		if (!employee->transfer && (!base || E_IsInBase(employee, base))) {
			LIST_AddPointer(hiredEmployees, employee);
		}
	}

	if (hiredEmployees == NULL)
		return 0;
	return LIST_Count(*hiredEmployees);
}
Example #13
0
/**
 * @brief Reads the sequence values from given text-pointer
 * @sa CL_ParseClientData
 */
void CL_ParseSequence (const char *name, const char **text)
{
	const char *errhead = "CL_ParseSequence: unexpected end of file (sequence ";
	sequence_t *sp;
	const char *token;
	int i;

	/* search for sequences with same name */
	for (i = 0; i < numSequences; i++)
		if (Q_streq(name, sequences[i].name))
			break;

	if (i < numSequences) {
		Com_Printf("CL_ParseSequence: sequence def \"%s\" with same name found, second ignored\n", name);
		return;
	}

	/* initialize the sequence */
	if (numSequences >= MAX_SEQUENCES)
		Com_Error(ERR_FATAL, "Too many sequences");

	sp = &sequences[numSequences++];
	OBJZERO(*sp);
	Q_strncpyz(sp->name, name, sizeof(sp->name));
	sp->start = numSeqCmds;

	/* get it's body */
	token = Com_Parse(text);

	if (!*text || *token != '{') {
		Com_Printf("CL_ParseSequence: sequence def \"%s\" without body ignored\n", name);
		numSequences--;
		return;
	}

	do {
		token = Com_EParse(text, errhead, name);
		if (!*text)
			break;
		if (*token == '}')
			break;

		/* check for commands */
		int i = CL_FindSequenceCommand(token);
		if (i != -1) {
			int maxLength = MAX_DATA_LENGTH;
			char *data;
			seqCmd_t *sc;

			/* found a command */
			token = Com_EParse(text, errhead, name);
			if (!*text)
				return;

			if (numSeqCmds >= MAX_SEQCMDS)
				Com_Error(ERR_FATAL, "Too many sequence commands for %s", name);

			/* init seqCmd */
			if (seqCmds == NULL)
				seqCmds = Mem_PoolAllocTypeN(seqCmd_t, MAX_SEQCMDS, cl_genericPool);
			sc = &seqCmds[numSeqCmds++];
			OBJZERO(*sc);
			sc->handler = seqCmdFunc[i];
			sp->length++;

			/* copy name */
			Q_strncpyz(sc->name, token, sizeof(sc->name));

			/* read data */
			token = Com_EParse(text, errhead, name);
			if (!*text)
				return;
			if (*token == '{') {
				// TODO depth is useless IMHO (bayo)
				int depth = 1;
				data = &sc->data[0];
				while (depth) {
					if (maxLength <= 0) {
						Com_Printf("Too much data for sequence %s", sc->name);
						break;
					}
					token = Com_EParse(text, errhead, name);
					if (!*text)
						return;

					if (*token == '{')
						depth++;
					else if (*token == '}')
						depth--;
					if (depth) {
						Q_strncpyz(data, token, maxLength);
						data += strlen(token) + 1;
						maxLength -= (strlen(token) + 1);
					}
				}
			} else if (*token == '(') {
				linkedList_t *list;
				Com_UnParseLastToken();
				if (!Com_ParseList(text, &list)) {
					Com_Error(ERR_DROP, "CL_ParseSequence: error while reading list (sequence \"%s\")", name);
				}
				data = &sc->data[0];
				for (linkedList_t *element = list; element != NULL; element = element->next) {
					if (maxLength <= 0) {
						Com_Printf("Too much data for sequence %s", sc->name);
						break;
					}
					const char* v = (char*)element->data;
					Q_strncpyz(data, v, maxLength);
					data += strlen(v) + 1;
					maxLength -= (strlen(v) + 1);
				}
				LIST_Delete(&list);
			} else {
				Com_UnParseLastToken();
			}
		} else {
			Com_Printf("CL_ParseSequence: unknown command \"%s\" ignored (sequence %s)\n", token, name);
			Com_EParse(text, errhead, name);
		}
	} while (*text);
}
static void testTeamDefsModelScriptData (void)
{
	int i;
	linkedList_t *armourPaths = NULL;

	for (i = 0; i < csi.numTeamDefs; i++) {
		int j;
		const teamDef_t *teamDef = &csi.teamDef[i];
		if (!teamDef->armour)
			continue;

		for (j = 0; j < csi.numODs; j++) {
			const objDef_t *od = INVSH_GetItemByIDX(j);
			if (!INV_IsArmour(od))
				continue;

			/* not for this team */
			if (!CHRSH_IsArmourUseableForTeam(od, teamDef))
				continue;

			if (!LIST_ContainsString(armourPaths, od->armourPath))
				LIST_AddString(&armourPaths, od->armourPath);
		}

		UFO_CU_ASSERT_TRUE_MSG(!LIST_IsEmpty(armourPaths), va("no armour definitions found for team %s - but armour is set to true",
				teamDef->id));

		LIST_Foreach(armourPaths, char const, armourPath) {
			nametypes_t l;

			for (l = NAME_NEUTRAL; l < NAME_LAST; l++) {
				linkedList_t *list = teamDef->models[l];
				int k;

				/* no models for this gender */
				if (!teamDef->numModels[l])
					continue;

				CU_ASSERT_PTR_NOT_NULL(list);
				for (k = 0; k < teamDef->numModels[l]; k++) {
					const char *path;

					CU_ASSERT_PTR_NOT_NULL_FATAL(list);
					path = (const char*)list->data;
					/* body */
					list = list->next;
					CU_ASSERT_PTR_NOT_NULL_FATAL(list);
					UFO_CU_ASSERT_TRUE_MSG(TEST_CheckModel(va("%s/%s", path, list->data)), va("%s does not exist in models/%s (teamDef: %s)",
							list->data, path, teamDef->id));
					UFO_CU_ASSERT_TRUE_MSG(TEST_CheckModel(va("%s%s/%s", path, armourPath, list->data)), va("%s does not exist in models/%s%s (teamDef: %s)",
							list->data, path, armourPath, teamDef->id));

					list = list->next;
					CU_ASSERT_PTR_NOT_NULL_FATAL(list);
					/* head */
					UFO_CU_ASSERT_TRUE_MSG(TEST_CheckModel(va("%s/%s", path, list->data)), va("%s does not exist in models/%s (teamDef: %s)",
							list->data, path, teamDef->id));
					UFO_CU_ASSERT_TRUE_MSG(TEST_CheckModel(va("%s%s/%s", path, armourPath, list->data)), va("%s does not exist in models/%s%s (teamDef: %s)",
							list->data, path, armourPath, teamDef->id));

					/* skip skin */
					/** @todo check that the skin is valid for the given model */
					list = list->next;
					CU_ASSERT_PTR_NOT_NULL_FATAL(list);

					/* new path */
					list = list->next;
				}
			}
		}

		LIST_Delete(&armourPaths);
	}
Example #15
0
static inline void UI_ExecuteCallAction (const uiAction_t* action, const uiCallContext_t *context)
{
	uiNode_t* callNode = NULL;
	uiAction_t* param;
	uiAction_t* left = action->d.nonTerminal.left;
	uiCallContext_t newContext;
	const value_t* callProperty = NULL;
	const char* path = left->d.terminal.d1.constString;

	if (left->type == EA_VALUE_PATHPROPERTY || left->type == EA_VALUE_PATHNODE)
		path = left->d.terminal.d1.constString;
	else if (left->type == EA_VALUE_PATHPROPERTY_WITHINJECTION || left->type == EA_VALUE_PATHNODE_WITHINJECTION)
		path = UI_GenInjectedString(left->d.terminal.d1.constString, false, context);
	UI_ReadNodePath(path, context->source, &callNode, &callProperty);

	if (callNode == NULL) {
		Com_Printf("UI_ExecuteCallAction: Node from path \"%s\" not found (relative to \"%s\").\n", path, UI_GetPath(context->source));
		return;
	}

	if (callProperty != NULL && callProperty->type != V_UI_ACTION && callProperty->type != V_UI_NODEMETHOD) {
		Com_Printf("UI_ExecuteCallAction: Call operand %d unsupported. (%s)\n", callProperty->type, UI_GetPath(callNode));
		return;
	}

	newContext.source = callNode;
	newContext.params = NULL;
	newContext.paramNumber = 0;
	newContext.varNumber = 0;
	newContext.varPosition = context->varPosition + context->varNumber;

	if (action->type == EA_LISTENER) {
		newContext.useCmdParam = context->useCmdParam;

		if (!newContext.useCmdParam) {
			linkedList_t *p = context->params;
			while (p) {
				const char* value = (char*) p->data;
				LIST_AddString(&newContext.params, value);
				newContext.paramNumber++;
				p = p->next;
			}
		}
	} else {
		newContext.useCmdParam = false;

		param = action->d.nonTerminal.right;
		while (param) {
			const char* value;
			value = UI_GetStringFromExpression(param, context);
			LIST_AddString(&newContext.params, value);
			newContext.paramNumber++;
			param = param->next;
		}
	}

	if (callProperty == NULL || callProperty->type == V_UI_ACTION) {
		uiAction_t const* const actionsRef = callProperty ? Com_GetValue<uiAction_t*>(callNode, callProperty) : callNode->onClick;
		UI_ExecuteActions(actionsRef, &newContext);
	} else if (callProperty->type == V_UI_NODEMETHOD) {
		uiNodeMethod_t func = (uiNodeMethod_t) callProperty->ofs;
		func(callNode, &newContext);
	} else {
		/* unreachable, already checked few line before */
		assert(false);
	}

	LIST_Delete(&newContext.params);
}
Example #16
0
/**
 * @sa CL_ParseScriptFirst
 */
static void CP_ParseAlienTeam (const char *name, const char **text)
{
	const char *errhead = "CP_ParseAlienTeam: unexpected end of file (alienteam ";
	const char *token;
	int i;
	alienTeamCategory_t *alienCategory;

	/* get it's body */
	token = Com_Parse(text);

	if (!*text || *token != '{') {
		Com_Printf("CP_ParseAlienTeam: alien team category \"%s\" without body ignored\n", name);
		return;
	}

	if (ccs.numAlienCategories >= ALIENCATEGORY_MAX) {
		Com_Printf("CP_ParseAlienTeam: maximum number of alien team category reached (%i)\n", ALIENCATEGORY_MAX);
		return;
	}

	/* search for category with same name */
	for (i = 0; i < ccs.numAlienCategories; i++)
		if (Q_streq(name, ccs.alienCategories[i].id))
			break;
	if (i < ccs.numAlienCategories) {
		Com_Printf("CP_ParseAlienTeam: alien category def \"%s\" with same name found, second ignored\n", name);
		return;
	}

	alienCategory = &ccs.alienCategories[ccs.numAlienCategories++];
	Q_strncpyz(alienCategory->id, name, sizeof(alienCategory->id));

	do {
		token = cgi->Com_EParse(text, errhead, name);
		if (!*text)
			break;
		if (*token == '}')
			break;

		if (Q_streq(token, "equipment")) {
			linkedList_t **list = &alienCategory->equipment;
			if (!Com_ParseList(text, list)) {
				cgi->Com_Error(ERR_DROP, "CL_ParseAlienTeam: \"%s\" Error while parsing equipment list", name);
			}
		} else if (Q_streq(token, "category")) {
			linkedList_t *list;
			if (!Com_ParseList(text, &list)) {
				cgi->Com_Error(ERR_DROP, "CL_ParseAlienTeam: \"%s\" Error while parsing category list", name);
			}
			for (linkedList_t *element = list; element != NULL; element = element->next) {
				alienCategory->missionCategories[alienCategory->numMissionCategories] = CP_GetAlienMissionTypeByID((char*)element->data);
				if (alienCategory->missionCategories[alienCategory->numMissionCategories] == INTERESTCATEGORY_NONE)
					Com_Printf("CP_ParseAlienTeam: alien team category \"%s\" is used with no mission category. It won't be used in game.\n", name);
				alienCategory->numMissionCategories++;
			}
			LIST_Delete(&list);
		} else if (Q_streq(token, "teaminterest")) {
			alienTeamGroup_t *group;

			token = cgi->Com_EParse(text, errhead, name);
			if (!*text || *token != '{') {
				Com_Printf("CP_ParseAlienTeam: alien team \"%s\" has team with no opening brace\n", name);
				break;
			}

			if (alienCategory->numAlienTeamGroups >= MAX_ALIEN_GROUP_PER_CATEGORY) {
				Com_Printf("CP_ParseAlienTeam: maximum number of alien team reached (%i) in category \"%s\"\n", MAX_ALIEN_GROUP_PER_CATEGORY, name);
				break;
			}

			group = &alienCategory->alienTeamGroups[alienCategory->numAlienTeamGroups];
			group->idx = alienCategory->numAlienTeamGroups;
			group->categoryIdx = alienCategory - ccs.alienCategories;
			alienCategory->numAlienTeamGroups++;

			do {
				token = cgi->Com_EParse(text, errhead, name);

				if (!Com_ParseBlockToken(name, text, group, alien_group_vals, cp_campaignPool, token)) {
					const teamDef_t *teamDef;
					if (!*text || *token == '}')
						break;

					if (Q_streq(token, "team")) {
						linkedList_t *list;
						if (!Com_ParseList(text, &list)) {
							cgi->Com_Error(ERR_DROP, "CL_ParseAlienTeam: \"%s\" Error while parsing team list", name);
						}
						for (linkedList_t *element = list; element != NULL; element = element->next) {
							if (group->numAlienTeams >= MAX_TEAMS_PER_MISSION)
								cgi->Com_Error(ERR_DROP, "CL_ParseAlienTeam: MAX_TEAMS_PER_MISSION hit");
							teamDef = cgi->Com_GetTeamDefinitionByID((char*)element->data);
							if (teamDef)
								group->alienTeams[group->numAlienTeams++] = teamDef;
						}
						LIST_Delete(&list);
					} else {
						cgi->Com_Error(ERR_DROP, "CL_ParseAlienTeam: Unknown token \"%s\"\n", token);
					}
				}
			} while (*text);
		} else {
			Com_Printf("CP_ParseAlienTeam: unknown token \"%s\" ignored (category %s)\n", token, name);
			continue;
		}
	} while (*text);

	if (LIST_IsEmpty(alienCategory->equipment))
		Sys_Error("alien category equipment list is empty");
}
Example #17
0
/**
 * @brief Start Base Attack.
 * @note Base attack mission -- Stage 2
 */
void CP_BaseAttackStartMission (mission_t *mission)
{
	base_t *base = mission->data.base;
	linkedList_t *hiredSoldiersInBase = NULL;
	employee_t *employee;

	assert(base);

	mission->stage = STAGE_BASE_ATTACK;

	CP_MissionDisableTimeLimit(mission);

	if (mission->ufo) {
		/* ufo becomes invisible on geoscape, but don't remove it from ufo global array (may reappear)*/
		CP_UFORemoveFromGeoscape(mission, qfalse);
	}

	/* we always need at least one command centre in the base - because the
	 * phalanx soldiers have their starting positions here.
	 * There should also always be an entrance - the aliens start there
	 * but we don't need to check that as entrance can't be destroyed */
	if (!B_GetNumberOfBuildingsInBaseByBuildingType(base, B_COMMAND)) {
		/** @todo handle command centre properly */
		Com_DPrintf(DEBUG_CLIENT, "CP_BaseAttackStartMission: Base '%s' has no Command Center: it can't defend itself. Destroy base.\n", base->name);
		CP_BaseAttackMissionDestroyBase(mission);
		return;
	}

	base->baseStatus = BASE_UNDER_ATTACK;
	ccs.campaignStats.basesAttacked++;

#if 0
	/** @todo implement onattack: add it to basemanagement.ufo and implement functions */
	if (base->onAttack[0] != '\0')
		/* execute next frame */
		Cbuf_AddText(va("%s %i", base->onAttack, base->id));
#endif

	MAP_SelectMission(mission);
	mission->active = qtrue;
	ccs.mapAction = MA_BASEATTACK;
	Com_DPrintf(DEBUG_CLIENT, "Base attack: %s at %.0f:%.0f\n", mission->id, mission->pos[0], mission->pos[1]);

	/** @todo EMPL_ROBOT */
	E_GetHiredEmployees(base, EMPL_SOLDIER, &hiredSoldiersInBase);

	/* Fill the fake aircraft */
	OBJZERO(baseAttackFakeAircraft);
	baseAttackFakeAircraft.homebase = base;
	/* needed for transfer of alien corpses */
	VectorCopy(base->pos, baseAttackFakeAircraft.pos);
#if 0
	/** @todo active this once more than 8 soldiers are working */
	/* needed to spawn soldiers on map */
	baseAttackFakeAircraft.maxTeamSize = LIST_Count(hiredSoldiersInBase);
#else
	baseAttackFakeAircraft.maxTeamSize = MAX_ACTIVETEAM;
#endif

	if (!hiredSoldiersInBase) {
		Com_DPrintf(DEBUG_CLIENT, "CP_BaseAttackStartMission: Base '%s' has no soldiers: it can't defend itself. Destroy base.\n", base->name);
		CP_BaseAttackMissionDestroyBase(mission);
		return;
	}

	LIST_Foreach(hiredSoldiersInBase, employee_t, employee) {
		if (E_IsAwayFromBase(employee))
			continue;
		AIR_AddToAircraftTeam(&baseAttackFakeAircraft, employee);
	}
	if (AIR_GetTeamSize(&baseAttackFakeAircraft) == 0) {
		Com_DPrintf(DEBUG_CLIENT, "CP_BaseAttackStartMission: Base '%s' has no soldiers at home: it can't defend itself. Destroy base.\n", base->name);
		CP_BaseAttackMissionDestroyBase(mission);
		return;
	}
#if 0
	/** @todo active this once more than 8 soldiers are working */
	/* all soldiers in the base should get used */
	baseAttackFakeAircraft.maxTeamSize = AIR_GetTeamSize(&baseAttackFakeAircraft);
#endif

	LIST_Delete(&hiredSoldiersInBase);
	base->aircraftCurrent = &baseAttackFakeAircraft;
	MAP_SetMissionAircraft(&baseAttackFakeAircraft);
	/** @todo remove me - this is not needed because we are using the base->aircraftCurrent
	 * pointer for resolving the aircraft - only CL_GameAutoGo needs this */
	MAP_SetInterceptorAircraft(&baseAttackFakeAircraft);	/* needed for updating soldier stats sa CL_UpdateCharacterStats*/
	B_SetCurrentSelectedBase(base);						/* needed for equipment menu */

	Com_sprintf(popupText, sizeof(popupText), _("Base '%s' is under attack! What to do ?"), base->name);
	UI_RegisterText(TEXT_POPUP, popupText);

	CL_GameTimeStop();
	UI_PushWindow("popup_baseattack", NULL, NULL);
}
Example #18
0
static inline void UI_ExecuteCallAction (const uiAction_t* action, const uiCallContext_t* context)
{
    uiNode_t* callNode = nullptr;
    uiAction_t* param;
    uiAction_t* left = action->d.nonTerminal.left;
    uiCallContext_t newContext;
    const value_t* callProperty = nullptr;
    value_t luaMethod;
    const char* path = left->d.terminal.d1.constString;

    // clear luaMethod structure before using it
    memset(&luaMethod, 0, sizeof(luaMethod));

    if (left->type == EA_VALUE_PATHPROPERTY || left->type == EA_VALUE_PATHNODE)
        path = left->d.terminal.d1.constString;
    else if (left->type == EA_VALUE_PATHPROPERTY_WITHINJECTION || left->type == EA_VALUE_PATHNODE_WITHINJECTION)
        path = UI_GenInjectedString(left->d.terminal.d1.constString, false, context);

    UI_ReadNodePath(path, context->source, context->tagNode, &callNode, &callProperty, &luaMethod);
    if ((callNode == nullptr) && (!luaMethod.type)) {
        Com_Printf("UI_ExecuteCallAction: Node from path \"%s\" not found (relative to \"%s\").\n", path, UI_GetPath(context->source));
        return;
    }
    if (callProperty != nullptr && callProperty->type != V_UI_ACTION && callProperty->type != V_UI_NODEMETHOD && callProperty->type != V_UI_NODEMETHOD_LUA) {
        Com_Printf("UI_ExecuteCallAction: Call operand %d unsupported. (%s)\n", callProperty->type, UI_GetPath(callNode));
        return;
    }

    newContext.source = callNode;
    newContext.params = nullptr;
    newContext.paramNumber = 0;
    newContext.varNumber = 0;
    newContext.varPosition = context->varPosition + context->varNumber;
    newContext.breakLoop = false;

    if (action->type == EA_LISTENER) {
        newContext.useCmdParam = context->useCmdParam;

        if (!newContext.useCmdParam) {
            linkedList_t* p = context->params;
            while (p) {
                const char* value = (char*) p->data;
                LIST_AddString(&newContext.params, value);
                newContext.paramNumber++;
                p = p->next;
            }
        }
    } else {
        newContext.useCmdParam = false;

        param = action->d.nonTerminal.right;
        while (param) {
            const char* value;
            value = UI_GetStringFromExpression(param, context);
            LIST_AddString(&newContext.params, value);
            newContext.paramNumber++;
            param = param->next;
        }
    }

    if (luaMethod.type == V_UI_NODEMETHOD_LUA) {
        UI_ExecuteLuaMethod(callNode, luaMethod.ofs, newContext.params, newContext.paramNumber);
        Mem_Free(const_cast<char*>(luaMethod.string));
    }
    else if (callProperty == nullptr || callProperty->type == V_UI_ACTION) {
        uiAction_t const* const actionsRef = callProperty ? Com_GetValue<uiAction_t*>(callNode, callProperty) : callNode->onClick;
        if (actionsRef)
            UI_ExecuteActions(actionsRef, &newContext);
        if (callNode->lua_onClick != LUA_NOREF)
            UI_ExecuteLuaMethod(callNode, callNode->lua_onClick, newContext.params, newContext.paramNumber);
    }
    else if (callProperty->type == V_UI_NODEMETHOD) {
        uiNodeMethod_t func = (uiNodeMethod_t) callProperty->ofs;
        func(callNode, &newContext);
    }
    else {
        /* unreachable, already checked few line before */
        assert(false);
    }

    LIST_Delete(&newContext.params);
}
Example #19
0
/**
 * @brief Make sure, that the linked list is freed with every new game
 * @sa CP_ResetCampaignData
 */
void CP_FreeDynamicEventMail (void)
{
	/* the pointers are not freed, this is done with the
	 * pool clear in CP_ResetCampaignData */
	LIST_Delete(&eventMails);
}
Example #20
0
/**
 * @brief Parse all language definitions from the script files
 */
void CL_ParseLanguages (const char* name, const char** text)
{
	const char* errhead = "CL_ParseLanguages: unexpected end of file (language ";
	const char* token;

	if (!*text) {
		Com_Printf("CL_ParseLanguages: language without body ignored (%s)\n", name);
		return;
	}

	token = Com_EParse(text, errhead, name);
	if (!*text || *token != '{') {
		Com_Printf("CL_ParseLanguages: language without body ignored (%s)\n", name);
		return;
	}

	language_t* const language = Mem_PoolAllocType(language_t, cl_genericPool);
	language->localeID = Mem_PoolStrDup(name, cl_genericPool, 0);
	language->localeString = "";
	language->nativeString = "";
	language->localeMapping = nullptr;

	do {
		/* get the name type */
		token = Com_EParse(text, errhead, name);
		if (!*text || *token == '}')
			break;
		/* inner locale id definition */
		if (Q_streq(token, "code")) {
			linkedList_t* list;
			if (!Com_ParseList(text, &list)) {
				Com_Error(ERR_DROP, "CL_ParseLanguages: error while reading language codes \"%s\"", name);
			}
			for (linkedList_t* element = list; element != nullptr; element = element->next) {
				localeMapping_t* const mapping = Mem_PoolAllocType(localeMapping_t, cl_genericPool);
				mapping->localeMapping = Mem_PoolStrDup((char*)element->data, cl_genericPool, 0);
				/* link it in */
				mapping->next = language->localeMapping;
				language->localeMapping = mapping;
			}
			LIST_Delete(&list);
		} else if (Q_streq(token, "name")) {
			token = Com_EParse(text, errhead, name);
			if (!*text || *token == '}')
				Com_Error(ERR_FATAL, "CL_ParseLanguages: Name expected for language \"%s\".\n", name);
			if (*token != '_') {
				Com_Printf("CL_ParseLanguages: language: '%s' - not marked translatable (%s)\n", name, token);
			}
			language->localeString = Mem_PoolStrDup(token, cl_genericPool, 0);
		} else if (Q_streq(token, "native")) {
			token = Com_EParse(text, errhead, name);
			if (!*text || *token == '}')
				Com_Error(ERR_FATAL, "CL_ParseLanguages: Native expected for language \"%s\".\n", name);
			language->nativeString = Mem_PoolStrDup(token, cl_genericPool, 0);
		}
	} while (*text);

	language->next = languageList;
	languageList = language;
	languageCount++;
}