Esempio n. 1
0
localModel_t* LM_GetByID (const char* id)
{
	if (Q_strnull(id))
		return nullptr;

	for (int i = 0; i < cl.numLMs; i++) {
		localModel_t* lm = &cl.LMs[i];
		if (Q_streq(lm->id, id))
			return lm;
	}
	return nullptr;
}
Esempio n. 2
0
/**
 * @brief Parses the next token from the current script on the stack
 * and store the result in @c parsedToken
 */
const char* GetToken ()
{
	const char* token = Com_Parse(&script.script_p, parsedToken, sizeof(parsedToken));
	if (!script.script_p) {
		/* not if the current script is a memory buffer */
		if (!Q_streq(script.filename, "memory buffer"))
			Mem_Free(script.buffer);
		assert(Q_strnull(parsedToken));
		return parsedToken;
	}

	return token;
}
Esempio n. 3
0
TEST_F(WebApiTest, FileManagement)
{
	if (Q_strnull(user) || Q_strnull(password))
		return;

	/* we can only upload files from within our user directory - so let's copy it there */
	if (!FS_FileExists("%s/" FILENAME, FS_Gamedir())) {
		byte* buf;
		const int size = FS_LoadFile(FILENAME, &buf);
		ASSERT_TRUE(size > 0);
		ASSERT_TRUE(nullptr != buf);
		FS_WriteFile(buf, size, FILENAME);
		FS_FreeFile(buf);
	}
	ASSERT_TRUE(WEB_CGameUpload(CGAME, CATEGORY, FILENAME));
	ASSERT_TRUE(WEB_CGameDownloadFromUser(CGAME, CATEGORY, FILE, web_userid->integer));
	const int countAfterUpload = WEB_CGameListForUser(CGAME, CATEGORY, web_userid->integer);
	ASSERT_TRUE(countAfterUpload != -1);
	ASSERT_TRUE(countAfterUpload >= 1);
	ASSERT_TRUE(WEB_CGameDelete(CGAME, CATEGORY, FILE));
	const int countAfterDelete = WEB_CGameListForUser(CGAME, CATEGORY, web_userid->integer);
	ASSERT_TRUE(countAfterDelete != -1);
	ASSERT_EQ(countAfterDelete, countAfterUpload - 1);
}
Esempio n. 4
0
ptlDef_t* CL_ParticleGet (const char* name)
{
	if (Q_strnull(name))
		return nullptr;

	/* find the particle definition */
	for (int i = 0; i < numPtlDefs; i++) {
		ptlDef_t* pd = &ptlDef[i];
		if (Q_streq(name, pd->name)) {
			return pd;
		}
	}

	return nullptr;
}
Esempio n. 5
0
static qboolean TEST_CheckModel (const char *path)
{
	const char *extensions[] = {"md2", "md3", "dpm", "obj", NULL};
	int i = 0;
	if (Q_strnull(path))
		return qtrue;

	while (extensions[i]) {
		if (FS_CheckFile("models/%s.%s", path, extensions[i]) != -1)
			return qtrue;
		i++;
	}

	return qfalse;
}
Esempio n. 6
0
static qboolean TEST_CheckImage (const char *path)
{
	const char *extensions[] = {"png", "tga", "jpg", NULL};
	int i = 0;

	if (Q_strnull(path))
		return qtrue;

	while (extensions[i]) {
		if (FS_CheckFile("pics/%s.%s", path, extensions[i]) != -1)
			return qtrue;
		i++;
	}

	return qfalse;
}
Esempio n. 7
0
static qboolean TEST_CheckSound (const char *path)
{
	const char *extensions[] = {"wav", "ogg", NULL};
	int i = 0;

	if (Q_strnull(path))
		return qtrue;

	while (extensions[i]) {
		if (FS_CheckFile("sound/%s.%s", path, extensions[i]) != -1)
			return qtrue;
		i++;
	}

	return qfalse;
}
Esempio n. 8
0
/**
 * @brief Set a binding from a key to a node to active.
 *
 * This command create a relation between a key and a node.
 *
 * The relation is stored to the node (to display the shortcut into tooltip)
 * and to parent window of the node (to faster search of all available shortcuts).
 *
 * The storage on the node is not a list, then if there is more than one shortcut
 * to a node we can't display all shortcut to tooltip, but the binding will still
 * work.
 *
 * If the parent window is inherited, the binding is dup to others extend
 * windows and the relation is flagged as "inherited".
 *
 * @param path Path to a node, or a node mathod
 * @param key The key number to use (see for example the K_* names are matched up.)
 * @param inherited True if this binding is inherited from another binding.
 *
 * @todo check: only one binding per nodes
 * @todo check: key per window must be unique
 * @todo check: key used into UI_KeyPressed can't be used
 */
static void UI_SetKeyBindingEx (const char* path, int key, const char* description, bool inherited)
{
	uiNode_t *node;
	uiKeyBinding_t *binding;
	const value_t *property = NULL;
	int windowId;
	char newPath[256];

	UI_ReadNodePath(path, NULL, &node, &property);
	if (node == NULL) {
		Com_Printf("UI_SetKeyBinding: node \"%s\" not found.\n", path);
		return;
	}

	if (property != NULL && property->type != V_UI_NODEMETHOD)
		Com_Error(ERR_FATAL, "UI_SetKeyBinding: Only node and method are supported. Property @%s not found in path \"%s\".", property->string, path);

	/* init and link the keybinding */
	binding = UI_AllocStaticKeyBinding();
	binding->node = node;
	binding->property = property;
	binding->key = key;
	binding->inherited = inherited;
	node->key = binding;

	if (Q_strnull(description))
		Com_Printf("Warning: Empty description for UI keybinding: %s (%s)\n", path, Key_KeynumToString(key));
	else
		binding->description = Mem_PoolStrDup(description, ui_dynPool, 0);;

	UI_WindowNodeRegisterKeyBinding(node->root, binding);

	/* search and update windows extend node->root */
	for (windowId = 0; windowId < ui_global.numWindows; windowId++) {
		uiNode_t *window = ui_global.windows[windowId];

		/* skip window which are not direct extends of the main window */
		if (window->super != node->root)
			continue;

		/* create a new patch from the new windows */
		newPath[0] = '\0';
		Q_strcat(newPath, window->name, sizeof(newPath));
		Q_strcat(newPath, path + strlen(node->root->name), sizeof(newPath));
		UI_SetKeyBindingEx(newPath, key, description, true);
	}
}
Esempio n. 9
0
int GameTest::testCountSpawnpointsGetNumteamValueForAircraft(const char *aircraft)
{
	// TODO: somehow fix these magic values here
	if (Q_strnull(aircraft)) {
		/* Could be any, so we return the max supported number. */
		return 12;
	} else if (Q_streq(aircraft, "craft_drop_firebird")) {
		return 8;
	} else if (Q_streq(aircraft, "craft_drop_raptor")) {
		return 10;
	} else if (Q_streq(aircraft, "craft_drop_herakles")) {
		return 12;
	} else {
		ADD_FAILURE() << "Error: Mapdef defines unknown aircraft: " << aircraft;
		return 0;
	}
}
Esempio n. 10
0
/**
 * @return true if the file exists, otherwise it attempts to start a download via curl
 * @sa CL_CheckAndQueueDownload
 * @sa CL_RequestNextDownload
 */
bool CL_CheckOrDownloadFile (const char *filename)
{
	static char lastfilename[MAX_OSPATH] = "";

	if (Q_strnull(filename))
		return true;

	/* r1: don't attempt same file many times */
	if (Q_streq(filename, lastfilename))
		return true;

	Q_strncpyz(lastfilename, filename, sizeof(lastfilename));

	if (strstr(filename, "..")) {
		Com_Printf("Refusing to check a path with .. (%s)\n", filename);
		return true;
	}

	if (strchr(filename, ' ')) {
		Com_Printf("Refusing to check a path containing spaces (%s)\n", filename);
		return true;
	}

	if (strchr(filename, ':')) {
		Com_Printf("Refusing to check a path containing a colon (%s)\n", filename);
		return true;
	}

	if (filename[0] == '/') {
		Com_Printf("Refusing to check a path starting with / (%s)\n", filename);
		return true;
	}

	if (FS_LoadFile(filename, NULL) != -1) {
		/* it exists, no need to download */
		return true;
	}

	if (CL_QueueHTTPDownload(filename))
		return false;

	return true;
}
Esempio n. 11
0
int GameTest::testCountSpawnpointsGetNum2x2ValueForAircraft(const char *aircraft)
{
	/* Right now, 2x2 units are not yet implemented. But if we start to, it will probably
	   be humans bringing UGVs into battle. So we should make sure there are at least some
	   2x2 spawnpoints for TEAM_HUMAN on each map.
	   The values are arbitrary, as they are not defined within the scripts yet. */

	if (Q_strnull(aircraft)) {
		/* Could be any, so we return the max supported number. */
		return 3;
	} else if (Q_streq(aircraft, "craft_drop_firebird")) {
		return 3;
	} else if (Q_streq(aircraft, "craft_drop_raptor")) {
		return 3;
	} else if (Q_streq(aircraft, "craft_drop_herakles")) {
		return 3;
	} else {
		ADD_FAILURE() << "Error: Mapdef defines unknown aircraft: " << aircraft;
		return 0;
	}
}
Esempio n. 12
0
/**
 * @brief Draws the texture node
 * @param[in] node The UI node to draw
 */
void uiTextureNode::draw (uiNode_t* node)
{
	vec2_t nodepos;
	const image_t* image;

	const char* imageName = UI_GetReferenceString(node, node->image);
	if (Q_strnull(imageName))
		return;

	image = UI_LoadWrappedImage(imageName);
	if (!image)
		return;

	/* avoid potential infinit loop */
	if (image->height == 0 || image->width == 0)
		return;

	UI_GetNodeAbsPos(node, nodepos);

	UI_DrawNormImage(false, nodepos[0], nodepos[1], node->box.size[0], node->box.size[1], node->box.size[0], node->box.size[1], 0, 0, image);
}
Esempio n. 13
0
/**
 * @brief Adds a new entry into string with given value.
 * @note Removed any old version of the key
 * @param[in,out] s The target info string
 * @param[in] size The size of @c s
 * @param[in] key The key to set
 * @param[in] value The value to set for the given key
 * @sa Info_RemoveKey
 * @sa Info_SetValueForKeyAsInteger
 */
void Info_SetValueForKey (char* s, const size_t size, const char* key, const char* value)
{
	char newi[MAX_INFO_STRING];

	if (strstr(key, "\\") || strstr(value, "\\")) {
		Com_Printf("Can't use keys or values with a \\\n");
		return;
	}

	if (strstr(key, ";")) {
		Com_Printf("Can't use keys or values with a semicolon\n");
		return;
	}

	if (strstr(key, "\"") || strstr(value, "\"")) {
		Com_Printf("Can't use keys or values with a \"\n");
		return;
	}

	if (strlen(key) > MAX_INFO_KEY - 1) {
		Com_Printf("Keys must be < " DOUBLEQUOTE(MAX_INFO_KEY) " characters.\n");
		return;
	}

	if (strlen(key) > MAX_INFO_VALUE - 1) {
		Com_Printf("Values must be < " DOUBLEQUOTE(MAX_INFO_VALUE) " characters.\n");
		return;
	}

	Info_RemoveKey(s, key);
	if (Q_strnull(value))
		return;

	Com_sprintf(newi, sizeof(newi), "\\%s\\%s%s", key, value, s);
	Q_strncpyz(s, newi, size);
}
Esempio n. 14
0
/**
 * @brief Parsed map entites and brushes
 * @sa ParseBrush
 * @param[in] filename The map filename
 * @param[in] entityString The body of the entity we are parsing
 */
static bool ParseMapEntity (const char* filename, const char* entityString)
{
	entity_t* mapent;
	const char* entName;
	static int worldspawnCount = 0;
	int notCheckOrFix = !(config.performMapCheck || config.fixMap);

	if (Q_strnull(GetToken()))
		return false;

	if (*parsedToken != '{')
		Sys_Error("ParseMapEntity: { not found");

	if (num_entities == MAX_MAP_ENTITIES)
		Sys_Error("num_entities == MAX_MAP_ENTITIES (%i)", num_entities);

	mapent = &entities[num_entities++];
	OBJZERO(*mapent);
	mapent->firstbrush = nummapbrushes;
	mapent->numbrushes = 0;

	do {
		if (Q_strnull(GetToken()))
			Sys_Error("ParseMapEntity: EOF without closing brace");
		if (*parsedToken == '}')
			break;
		if (*parsedToken == '{')
			ParseBrush(mapent, filename);
		else {
			epair_t* e = ParseEpair(num_entities);
			e->next = mapent->epairs;
			mapent->epairs = e;
		}
	} while (true);

	GetVectorForKey(mapent, "origin", mapent->origin);

	entName = ValueForKey(mapent, "classname");

	/* offset all of the planes and texinfo if needed */
	if (IsInlineModelEntity(entName) && VectorNotEmpty(mapent->origin))
		AdjustBrushesForOrigin(mapent);

	if (num_entities == 1 && !Q_streq("worldspawn", entName))
		Sys_Error("The first entity must be worldspawn, it is: %s", entName);
	if (notCheckOrFix && Q_streq("func_group", entName)) {
		/* group entities are just for editor convenience
		 * toss all brushes into the world entity */
		MoveBrushesToWorld(mapent);
		num_entities--;
	} else if (IsInlineModelEntity(entName)) {
		if (mapent->numbrushes == 0 && notCheckOrFix) {
			Com_Printf("Warning: %s has no brushes assigned (entnum: %i)\n", entName, num_entities);
			num_entities--;
		}
	} else if (Q_streq("worldspawn", entName)) {
		worldspawnCount++;
		if (worldspawnCount > 1)
			Com_Printf("Warning: more than one %s in one map\n", entName);

		const char* text = entityString;
		do {
			const char* token = Com_Parse(&text);
			if (Q_strnull(token))
				break;
			const char* key = Mem_StrDup(token);
			token = Com_Parse(&text);
			if (Q_strnull(token))
				break;
			const char* value = Mem_StrDup(token);
			epair_t* e = AddEpair(key, value, num_entities);
			e->next = mapent->epairs;
			mapent->epairs = e;
		} while (true);
	}
	return true;
}
Esempio n. 15
0
/**
 * @todo need to merge UI model case, and the common case (looks to be a copy-pasted code)
 */
void UI_DrawModelNode (uiNode_t* node, const char* source)
{
	modelInfo_t mi;
	uiModel_t* model;
	vec3_t nodeorigin;
	vec2_t screenPos;

	assert(UI_NodeInstanceOf(node, "model"));			/**< We use model extradata */

	if (!source || source[0] == '\0')
		return;

	model = UI_GetUIModel(source);
	/* direct model name - no UI model definition */
	if (!model) {
		/* prevent the searching for a model def in the next frame */
		mi.model = R_FindModel(source);
		mi.name = source;
		if (!mi.model) {
			Com_Printf("Could not find model '%s'\n", source);
			return;
		}
	}

	/* compute the absolute origin ('origin' property is relative to the node center) */
	UI_GetNodeScreenPos(node, screenPos);
	UI_GetNodeAbsPos(node, nodeorigin);
	R_CleanupDepthBuffer(nodeorigin[0], nodeorigin[1], node->box.size[0], node->box.size[1]);
	if (EXTRADATA(node).clipOverflow) {
		UI_PushClipRect(screenPos[0], screenPos[1], node->box.size[0], node->box.size[1]);
	}
	nodeorigin[0] += node->box.size[0] / 2 + EXTRADATA(node).origin[0];
	nodeorigin[1] += node->box.size[1] / 2 + EXTRADATA(node).origin[1];
	nodeorigin[2] = EXTRADATA(node).origin[2];

	VectorMA(EXTRADATA(node).angles, cls.frametime, EXTRADATA(node).omega, EXTRADATA(node).angles);
	mi.origin = nodeorigin;
	mi.angles = EXTRADATA(node).angles;
	mi.scale = EXTRADATA(node).scale;
	mi.center = nullVector;
	mi.color = node->color;
	mi.mesh = 0;

	/* special case to draw models with UI model */
	if (model) {
		UI_DrawModelNodeWithUIModel(node, source, &mi, model);
		if (EXTRADATA(node).clipOverflow)
			UI_PopClipRect();
		return;
	}

	/* if the node is linked to a parent, the parent will display it */
	if (EXTRADATA(node).tag) {
		if (EXTRADATA(node).clipOverflow)
			UI_PopClipRect();
		return;
	}

	/* autoscale? */
	if (EXTRADATA(node).autoscale) {
		vec3_t autoScale;
		vec3_t autoCenter;
		const vec2_t size = {node->box.size[0] - node->padding, node->box.size[1] - node->padding};
		R_ModelAutoScale(size, &mi, autoScale, autoCenter);
	}

	/* no animation */
	mi.frame = 0;
	mi.oldframe = 0;
	mi.backlerp = 0;

	/* get skin */
	if (EXTRADATA(node).skin && *EXTRADATA(node).skin)
		mi.skin = atoi(UI_GetReferenceString(node, EXTRADATA(node).skin));
	else
		mi.skin = 0;

	/* do animations */
	if (EXTRADATA(node).animation && *EXTRADATA(node).animation) {
		const char* ref;
		ref = UI_GetReferenceString(node, EXTRADATA(node).animation);

		/* check whether the cvar value changed */
		if (strncmp(EXTRADATA(node).oldRefValue, source, MAX_OLDREFVALUE)) {
			Q_strncpyz(EXTRADATA(node).oldRefValue, source, MAX_OLDREFVALUE);
			/* model has changed but mem is already reserved in pool */
			Mem_Free(EXTRADATA(node).animationState);
			EXTRADATA(node).animationState = nullptr;
		}
		animState_t* as = EXTRADATA(node).animationState;
		if (!as) {
			as = Mem_PoolAllocType(animState_t, cl_genericPool);
			if (!as)
				Com_Error(ERR_DROP, "Model %s should have animState_t for animation %s - but doesn't\n", mi.name, ref);
			R_AnimChange(as, mi.model, ref);
			EXTRADATA(node).animationState = as;
		} else {
			const char* anim;
			/* change anim if needed */
			anim = R_AnimGetName(as, mi.model);
			if (anim && !Q_streq(anim, ref))
				R_AnimChange(as, mi.model, ref);
			R_AnimRun(as, mi.model, cls.frametime * 1000);
		}

		mi.frame = as->frame;
		mi.oldframe = as->oldframe;
		mi.backlerp = as->backlerp;
	}

	/* draw the main model on the node */
	R_DrawModelDirect(&mi, nullptr, nullptr);

	/* draw all children */
	if (node->firstChild) {
		uiNode_t* child;
		modelInfo_t pmi = mi;
		for (child = node->firstChild; child; child = child->next) {
			const char* tag;
			char childSource[MAX_VAR];
			const char* childRef;

			/* skip non "model" nodes */
			if (child->behaviour != node->behaviour)
				continue;

			/* skip invisible child */
			if (child->invis || !UI_CheckVisibility(child))
				continue;

			OBJZERO(mi);
			mi.angles = EXTRADATA(child).angles;
			mi.scale = EXTRADATA(child).scale;
			mi.center = nullVector;
			mi.origin = EXTRADATA(child).origin;
			mi.color = pmi.color;

			/* get the anchor name to link the model into the parent */
			tag = EXTRADATA(child).tag;

			/* init model name */
			childRef = UI_GetReferenceString(child, EXTRADATA(child).model);
			if (Q_strnull(childRef))
				childSource[0] = '\0';
			else
				Q_strncpyz(childSource, childRef, sizeof(childSource));
			mi.model = R_FindModel(childSource);
			mi.name = childSource;

			/* init skin */
			if (EXTRADATA(child).skin && *EXTRADATA(child).skin)
				mi.skin = atoi(UI_GetReferenceString(child, EXTRADATA(child).skin));
			else
				mi.skin = 0;

			R_DrawModelDirect(&mi, &pmi, tag);
		}
	}

	if (EXTRADATA(node).clipOverflow)
		UI_PopClipRect();
}
Esempio n. 16
0
/**
 * @brief Spawn a new particle to the map
 * @param[in] name The id of the particle (see ptl_*.ufo script files in base/ufos)
 * @param[in] levelFlags Show at which levels
 * @param[in] s starting/location vector
 * @param[in] v velocity vector
 * @param[in] a acceleration vector
 * @sa CL_ParticleFree
 * @sa CL_ViewUpdateRenderData
 * @sa R_DrawParticles
 */
ptl_t* CL_ParticleSpawn (const char* name, int levelFlags, const vec3_t s, const vec3_t v, const vec3_t a)
{
	int i;

	if (Q_strnull(name))
		return nullptr;

	/* find the particle definition */
	ptlDef_t* pd = CL_ParticleGet(name);
	if (pd == nullptr) {
		Com_Printf("Particle definition \"%s\" not found\n", name);
		return nullptr;
	}

	/* add the particle */
	for (i = 0; i < r_numParticles; i++)
		if (!r_particleArray[i].inuse)
			break;

	if (i == r_numParticles) {
		if (r_numParticles < MAX_PTLS)
			r_numParticles++;
		else {
			Com_DPrintf(DEBUG_CLIENT, "Too many particles (don't add %s) - exceeded %i\n", name, MAX_PTLS);
			return nullptr;
		}
	}

	/* allocate particle */
	ptl_t* p = &r_particleArray[i];
	OBJZERO(*p);

	/* set basic values */
	p->inuse = true;
	p->startTime = cl.time;
	p->ctrl = pd;
	Vector4Set(p->color, 1.0f, 1.0f, 1.0f, 1.0f);

	p->pic = nullptr;
	p->model = nullptr;

	/* copy location */
	if (s) {
		VectorCopy(s, p->origin);
		VectorCopy(s, p->s);
	}
	/* copy velocity */
	if (v)
		VectorCopy(v, p->v);
	/* copy acceleration */
	if (a)
		VectorCopy(a, p->a);

	/* copy levelflags */
	p->levelFlags = levelFlags;

	/* run init function */
	CL_ParticleFunction(p, pd->init);
	if (p->inuse && !p->tps && !p->life) {
		Com_DPrintf(DEBUG_CLIENT, "Particle %s does not have a tps nor a life set - this is only valid for projectile particles\n",
				name);
		p->tps = 1;
	}

	return p;
}
Esempio n. 17
0
/**
 * @brief Serverbrowser text
 * @sa CL_PingServer
 * @sa CL_PingServers_f
 * @note This function fills the network browser server information with text
 * @sa NET_OOB_Printf
 * @sa CL_ServerInfoCallback
 * @sa SVC_Info
 */
static void GAME_MP_ParseServerInfoMessage (dbuffer* msg, const char* hostname)
{
	char str[MAX_INFO_STRING];

	cgi->NET_ReadString(msg, str, sizeof(str));

	/* check for server status response message */
	const char* value = Info_ValueForKey(str, "sv_dedicated");
	if (Q_strnull(value)) {
		cgi->Com_Printf(S_COLOR_GREEN "%s", str);
		return;
	}

	/* server info cvars and users are seperated via newline */
	const char* users = strstr(str, "\n");
	if (users == nullptr) {
		cgi->Com_Printf(S_COLOR_GREEN "%s\n", str);
		return;
	}
	cgi->Com_DPrintf(DEBUG_CLIENT, "%s\n", str); /* status string */

	cgi->Cvar_Set("mn_mappic", "maps/shots/default");
	if (*Info_ValueForKey(str, "sv_needpass") == '1')
		cgi->Cvar_Set("mn_server_need_password", "1");
	else
		cgi->Cvar_Set("mn_server_need_password", "0");

	Com_sprintf(serverInfoText, sizeof(serverInfoText), _("IP\t%s\n\n"), hostname);
	cgi->Cvar_Set("mn_server_ip", "%s", hostname);
	value = Info_ValueForKey(str, "sv_mapname");
	assert(value);
	cgi->Cvar_Set("mn_svmapname", "%s", value);
	char buf[256];
	Q_strncpyz(buf, value, sizeof(buf));
	const char* token = buf;
	/* skip random map char. */
	if (token[0] == '+')
		token++;

	Q_strcat(serverInfoText, sizeof(serverInfoText), _("Map:\t%s\n"), value);
	if (!cgi->R_ImageExists("pics/maps/shots/%s", token)) {
		/* store it relative to pics/ dir - not relative to game dir */
		cgi->Cvar_Set("mn_mappic", "maps/shots/%s", token);
	}
	Q_strcat(serverInfoText, sizeof(serverInfoText), _("Servername:\t%s\n"), Info_ValueForKey(str, "sv_hostname"));
	Q_strcat(serverInfoText, sizeof(serverInfoText), _("Moralestates:\t%s\n"), _(Info_BoolForKey(str, "sv_enablemorale")));
	Q_strcat(serverInfoText, sizeof(serverInfoText), _("Gametype:\t%s\n"), Info_ValueForKey(str, "sv_gametype"));
	Q_strcat(serverInfoText, sizeof(serverInfoText), _("Gameversion:\t%s\n"), Info_ValueForKey(str, "ver"));
	Q_strcat(serverInfoText, sizeof(serverInfoText), _("Dedicated server:\t%s\n"), _(Info_BoolForKey(str, "sv_dedicated")));
	Q_strcat(serverInfoText, sizeof(serverInfoText), _("Operating system:\t%s\n"), Info_ValueForKey(str, "sys_os"));
	Q_strcat(serverInfoText, sizeof(serverInfoText), _("Network protocol:\t%s\n"), Info_ValueForKey(str, "sv_protocol"));
	Q_strcat(serverInfoText, sizeof(serverInfoText), _("Roundtime:\t%s\n"), Info_ValueForKey(str, "sv_roundtimelimit"));
	Q_strcat(serverInfoText, sizeof(serverInfoText), _("Teamplay:\t%s\n"), _(Info_BoolForKey(str, "sv_teamplay")));
	Q_strcat(serverInfoText, sizeof(serverInfoText), _("Max. players per team:\t%s\n"), Info_ValueForKey(str, "sv_maxplayersperteam"));
	Q_strcat(serverInfoText, sizeof(serverInfoText), _("Max. teams allowed in this map:\t%s\n"), Info_ValueForKey(str, "sv_maxteams"));
	Q_strcat(serverInfoText, sizeof(serverInfoText), _("Max. clients:\t%s\n"), Info_ValueForKey(str, "sv_maxclients"));
	Q_strcat(serverInfoText, sizeof(serverInfoText), _("Max. soldiers per player:\t%s\n"), Info_ValueForKey(str, "sv_maxsoldiersperplayer"));
	Q_strcat(serverInfoText, sizeof(serverInfoText), _("Max. soldiers per team:\t%s\n"), Info_ValueForKey(str, "sv_maxsoldiersperteam"));
	Q_strcat(serverInfoText, sizeof(serverInfoText), _("Password protected:\t%s\n"), _(Info_BoolForKey(str, "sv_needpass")));
	cgi->UI_RegisterText(TEXT_STANDARD, serverInfoText);
	userInfoText[0] = '\0';
	for (;;) {
		token = Com_Parse(&users);
		if (users == nullptr)
			break;
		const int team = atoi(token);
		token = Com_Parse(&users);
		if (users == nullptr)
			break;
		Q_strcat(userInfoText, sizeof(userInfoText), "%s\t%i\n", token, team);
	}
	cgi->UI_RegisterText(TEXT_LIST, userInfoText);
	cgi->UI_PushWindow("serverinfo");
}
Esempio n. 18
0
/**
 * @brief Draws an item to the screen
 * @param[in] node Context node
 * @param[in] org Node position on the screen (pixel). Single nodes: Use the center of the node.
 * @param[in] item The item to draw.
 * @param[in] x Position in container. Set this to -1 if it's drawn in a single container.
 * @param[in] y Position in container. Set this to -1 if it's drawn in a single container.
 * @param[in] scale
 * @param[in] color
 * @sa SCR_DrawCursor
 * Used to draw an item to the equipment containers. First look whether the objDef_t
 * includes an image - if there is none then draw the model
 */
void UI_DrawItem (uiNode_t *node, const vec3_t org, const item_t *item, int x, int y, const vec3_t scale, const vec4_t color)
{
	const objDef_t *od = item->item;
	vec4_t col;
	vec3_t origin;

	assert(od);
	assert(org[2] > -1000 && org[2] < 1000); 	/*< prevent use of vec2_t for org */

	Vector4Copy(color, col);
	/* no ammo in this weapon - highlight this item */
	if (od->weapon && od->reload && !item->ammoLeft) {
		col[1] *= 0.5;
		col[2] *= 0.5;
	}

	VectorCopy(org, origin);

	/* Calculate correct location of the image or the model (depends on rotation) */
	/** @todo Change the rotation of the image as well, right now only the location is changed.
	 * How is image-rotation handled right now? */
	if (x >= 0 || y >= 0) {
		/* Add offset of location in container. */
		origin[0] += x * C_UNIT;
		origin[1] += y * C_UNIT;

		/* Add offset for item-center (depends on rotation). */
		if (item->rotated) {
			origin[0] += od->sy * C_UNIT / 2.0;
			origin[1] += od->sx * C_UNIT / 2.0;
			/** @todo Image size calculation depends on handling of image-rotation.
			imgWidth = od->sy * C_UNIT;
			imgHeight = od->sx * C_UNIT;
			*/
		} else {
			origin[0] += od->sx * C_UNIT / 2.0;
			origin[1] += od->sy * C_UNIT / 2.0;
		}
	}

	/* don't handle the od->tech->image here - it's very ufopedia specific in most cases */
	if (od->image[0] != '\0') {
		const int imgWidth = od->sx * C_UNIT;
		const int imgHeight = od->sy * C_UNIT;
		origin[0] -= od->sx * C_UNIT / 2.0;
		origin[1] -= od->sy * C_UNIT / 2.0;

		/* Draw the image. */
		R_Color(color);
		UI_DrawNormImageByName(false, origin[0], origin[1], imgWidth, imgHeight, 0, 0, 0, 0, od->image);
		R_Color(NULL);
	} else {
		uiModel_t *model = NULL;
		const char *modelName = GAME_GetModelForItem(od, &model);

		/* no model definition in the tech struct, not in the fallback object definition */
		if (Q_strnull(modelName)) {
			Com_Printf("UI_DrawItem: No model given for item: '%s'\n", od->id);
			return;
		}

		if (model && node) {
			UI_DrawModelNode(node, modelName);
		} else {
			modelInfo_t mi;
			vec3_t angles = {-10, 160, 70};
			vec3_t size = {scale[0], scale[1], scale[2]};
			vec3_t center;

			if (item->rotated)
				angles[0] -= 90;

			if (od->scale)
				VectorScale(size, od->scale, size);

			VectorNegate(od->center, center);

			OBJZERO(mi);
			mi.origin = origin;
			mi.angles = angles;
			mi.center = center;
			mi.scale = size;
			mi.color = col;
			mi.name = modelName;

			/* draw the model */
			R_DrawModelDirect(&mi, NULL, NULL);
		}
	}
}
Esempio n. 19
0
/**
 * @brief Draws a model in 2d mode (for rendering model data from the ui)
 * @param[in,out] mi All the needed model information to render the model
 * @param[in,out] pmi The model information of the parent model. This is used
 * in those cases, where the model that should get rendered here is placed relativly
 * to an already existing model in the world.
 * @param[in] tagname If a parent model is given, a @c tagname is given in most cases, too. It's used
 * to transform the model location relative to the parent model location again. E.g. a
 * @c tagname of tag_rweapon will transform the location to the right hand of an actor.
 * @sa R_DrawAliasModel
 */
void R_DrawModelDirect (modelInfo_t * mi, modelInfo_t * pmi, const char *tagname)
{
	image_t *skin;
	mAliasMesh_t *mesh;

	if (Q_strnull(mi->name))
		return;

	/* register the model */
	mi->model = R_FindModel(mi->name);

	/* check if the model exists */
	if (!mi->model) {
		Com_Printf("No model found for '%s'\n", mi->name);
		return;
	}

	skin = R_AliasModelState(mi->model, &mi->mesh, &mi->frame, &mi->oldframe, &mi->skin);
	if (skin == NULL) {
		Com_Printf("Model '%s' is broken\n", mi->name);
		return;
	}

	glPushMatrix();
	glScalef(viddef.rx, viddef.ry, (viddef.rx + viddef.ry) / 2);

	R_Color(mi->color);

	if (pmi) {
		/* register the parent model */
		pmi->model = R_FindModel(pmi->name);

		/* transform - the next transform for the child model will be relative from the
		 * parent model location now */
		R_TransformModelDirect(pmi);

		/* tag transformation */
		if (tagname) {
			const mAliasTagOrientation_t *current = NULL;
			const mAliasTagOrientation_t *old = NULL;
			R_GetTags(pmi->model, tagname, pmi->frame, pmi->oldframe, &current, &old);
			if (current != NULL && old != NULL) {
				float interpolated[16];

				/* do interpolation */
				R_InterpolateTransform(pmi->backlerp, pmi->model->alias.num_frames, current, old, interpolated);

				/* transform */
				glMultMatrixf(interpolated);
				R_CheckError();
			}
		}
	}

	/* transform */
	R_TransformModelDirect(mi);

	/* we have to reenable this here - we are in 2d mode here already */
	glEnable(GL_DEPTH_TEST);

	/* draw it */
	R_BindTexture(skin->texnum);

	/* draw the model */
	mesh = &mi->model->alias.meshes[0];
	refdef.aliasCount += mesh->num_tris;
	if (mi->model->alias.num_frames == 1)
		R_DrawAliasStaticWithReset(mesh, vec4_origin);
	else
		R_DrawAliasFrameLerp(&mi->model->alias, mesh, mi->backlerp, mi->frame, mi->oldframe, vec4_origin);

	/* show model bounding box */
	if (r_showbox->integer)
		R_DrawBoundingBox(mi->model->alias.frames[mi->frame].mins, mi->model->alias.frames[mi->frame].maxs);

	glDisable(GL_DEPTH_TEST);

	glPopMatrix();

	R_Color(NULL);
}
Esempio n. 20
0
void uiEkgNode::draw (uiNode_t *node)
{
	vec2_t size;
	vec2_t nodepos;
	const image_t *image;

	const char* imageName = UI_GetReferenceString(node, EXTRADATA(node).super.source);
	if (Q_strnull(imageName))
		return;

	UI_GetNodeAbsPos(node, nodepos);

	image = UI_LoadWrappedImage(imageName);
	if (image) {
		const int ekgHeight = node->box.size[1];
		const int ekgWidth = image->width;
		/* we have different ekg parts in each ekg image... */
		const int ekgImageParts = image->height / node->box.size[1];
		const int ekgMaxIndex = ekgImageParts - 1;
		/* we change the index of the image part in 20s steps */
		/** @todo this magic number should be replaced with a sane calculation of the value */
		const int ekgDivide = 20;
		/* If we are in the range of (ekgMaxValue + ekgDivide, ekgMaxValue) we are using the first image */
		const int ekgMaxValue = ekgDivide * ekgMaxIndex;
		int ekgValue;
		float current;

		/** @todo these cvars should come from the script */
		/* ekg_morale and ekg_hp are the node names */
		if (node->name[0] == 'm')
			current = Cvar_GetValue("mn_morale") / EXTRADATA(node).scaleCvarValue;
		else
			current = Cvar_GetValue("mn_hp") / EXTRADATA(node).scaleCvarValue;

		ekgValue = std::min((int)current, ekgMaxValue);

		EXTRADATA(node).super.texl[1] = (ekgMaxIndex - (int)(ekgValue / ekgDivide)) * ekgHeight;
		EXTRADATA(node).super.texh[1] = EXTRADATA(node).super.texl[1] + ekgHeight;
		EXTRADATA(node).super.texl[0] = -(int) (EXTRADATA(node).scrollSpeed * CL_Milliseconds()) % ekgWidth;
		EXTRADATA(node).super.texh[0] = EXTRADATA(node).super.texl[0] + node->box.size[0];
		/** @todo code is duplicated in the image node code */
		if (node->box.size[0] && !node->box.size[1]) {
			const float scale = image->width / node->box.size[0];
			Vector2Set(size, node->box.size[0], image->height / scale);
		} else if (node->box.size[1] && !node->box.size[0]) {
			const float scale = image->height / node->box.size[1];
			Vector2Set(size, image->width / scale, node->box.size[1]);
		} else {
			if (EXTRADATA(node).super.preventRatio) {
				/* maximize the image into the bounding box */
				const float ratio = (float) image->width / (float) image->height;
				if (node->box.size[1] * ratio > node->box.size[0]) {
					Vector2Set(size, node->box.size[0], node->box.size[0] / ratio);
				} else {
					Vector2Set(size, node->box.size[1] * ratio, node->box.size[1]);
				}
			} else {
				Vector2Copy(node->box.size, size);
			}
		}
		UI_DrawNormImage(false, nodepos[0], nodepos[1], size[0], size[1],
				EXTRADATA(node).super.texh[0], EXTRADATA(node).super.texh[1], EXTRADATA(node).super.texl[0], EXTRADATA(node).super.texl[1], image);
	}
}
Esempio n. 21
0
/**
 * @brief A connection request that did not come from the master
 * @sa CL_ConnectionlessPacket
 */
static void SVC_DirectConnect (struct net_stream* stream)
{
    Com_DPrintf(DEBUG_SERVER, "SVC_DirectConnect()\n");

    if (sv->started || sv->spawned) {
        Com_Printf("rejected connect because match is already running\n");
        NET_OOB_Printf(stream, SV_CMD_PRINT "\n" REJ_GAME_ALREADY_STARTED "\n");
        return;
    }

    char buf[256];
    const char* peername = NET_StreamPeerToName(stream, buf, sizeof(buf), false);

    const int version = atoi(Cmd_Argv(1));
    if (version != PROTOCOL_VERSION) {
        Com_Printf("rejected connect from version %i - %s\n", version, peername);
        NET_OOB_Printf(stream, SV_CMD_PRINT "\n" REJ_SERVER_VERSION_MISMATCH "\n");
        return;
    }

    char userinfo[MAX_INFO_STRING];
    Q_strncpyz(userinfo, Cmd_Argv(2), sizeof(userinfo));

    if (Q_strnull(userinfo)) {  /* catch empty userinfo */
        Com_Printf("Empty userinfo from %s\n", peername);
        NET_OOB_Printf(stream, SV_CMD_PRINT "\n" REJ_CONNECTION_REFUSED "\n");
        return;
    }

    if (strchr(userinfo, '\xFF')) {  /* catch end of message in string exploit */
        Com_Printf("Illegal userinfo contained xFF from %s\n", peername);
        NET_OOB_Printf(stream, SV_CMD_PRINT "\n" REJ_CONNECTION_REFUSED "\n");
        return;
    }

    if (strlen(Info_ValueForKey(userinfo, "ip"))) {  /* catch spoofed ips  */
        Com_Printf("Illegal userinfo contained ip from %s\n", peername);
        NET_OOB_Printf(stream, SV_CMD_PRINT "\n" REJ_CONNECTION_REFUSED "\n");
        return;
    }

    /* force the IP key/value pair so the game can filter based on ip */
    Info_SetValueForKey(userinfo, sizeof(userinfo), "ip", peername);

    /* find a client slot */
    client_t* cl = nullptr;
    while ((cl = SV_GetNextClient(cl)) != nullptr)
        if (cl->state == cs_free)
            break;
    if (cl == nullptr) {
        NET_OOB_Printf(stream, SV_CMD_PRINT "\n" REJ_SERVER_FULL "\n");
        Com_Printf("Rejected a connection - server is full.\n");
        return;
    }

    /* build a new connection - accept the new client
     * this is the only place a client_t is ever initialized */
    OBJZERO(*cl);
    const int playernum = cl - SV_GetClient(0);
    SrvPlayer* player = PLAYER_NUM(playernum);
    cl->player = player;
    cl->player->setNum(playernum);

    bool connected;
    {
        const ScopedMutex scopedMutex(svs.serverMutex);
        connected = svs.ge->ClientConnect(player, userinfo, sizeof(userinfo));
    }

    /* get the game a chance to reject this connection or modify the userinfo */
    if (!connected) {
        const char* rejmsg = Info_ValueForKey(userinfo, "rejmsg");
        if (rejmsg[0] != '\0') {
            NET_OOB_Printf(stream, SV_CMD_PRINT "\n%s\n" REJ_CONNECTION_REFUSED "\n", rejmsg);
            Com_Printf("Game rejected a connection from %s. Reason: %s\n", peername, rejmsg);
        } else {
            NET_OOB_Printf(stream, SV_CMD_PRINT "\n" REJ_CONNECTION_REFUSED "\n");
            Com_Printf("Game rejected a connection from %s.\n", peername);
        }
        return;
    }

    /* new player */
    cl->player->setInUse(true);
    cl->lastmessage = svs.realtime;

    /* parse some info from the info strings */
    Q_strncpyz(cl->userinfo, userinfo, sizeof(cl->userinfo));
    SV_UserinfoChanged(cl);

    /* send the connect packet to the client */
    if (sv_http_downloadserver->string[0])
        NET_OOB_Printf(stream, CL_CMD_CLIENT_CONNECT " dlserver=%s", sv_http_downloadserver->string);
    else
        NET_OOB_Printf(stream, CL_CMD_CLIENT_CONNECT);

    SV_SetClientState(cl, cs_connected);

    Q_strncpyz(cl->peername, peername, sizeof(cl->peername));
    cl->stream = stream;
    NET_StreamSetData(stream, cl);
}
Esempio n. 22
0
/**
 * @brief Parses a brush from the map file
 * @sa FindMiptex
 * @param[in] mapent The entity the brush to parse belongs to
 * @param[in] filename The map filename, used to derive the name for the footsteps file
 */
static void ParseBrush (entity_t* mapent, const char* filename)
{
	int j, k;
	brush_texture_t td;
	vec3_t planepts[3];
	const int checkOrFix = config.performMapCheck || config.fixMap ;

	if (nummapbrushes == MAX_MAP_BRUSHES)
		Sys_Error("nummapbrushes == MAX_MAP_BRUSHES (%i)", nummapbrushes);

	mapbrush_t* b = &mapbrushes[nummapbrushes];
	OBJZERO(*b);
	b->original_sides = &brushsides[nummapbrushsides];
	b->entitynum = num_entities - 1;
	b->brushnum = nummapbrushes - mapent->firstbrush;

	do {
		if (Q_strnull(GetToken()))
			break;
		if (*parsedToken == '}')
			break;

		if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
			Sys_Error("nummapbrushsides == MAX_MAP_BRUSHSIDES (%i)", nummapbrushsides);
		side_t* side = &brushsides[nummapbrushsides];

		/* read the three point plane definition */
		for (int i = 0; i < 3; i++) {
			if (i != 0)
				GetToken();
			if (*parsedToken != '(')
				Sys_Error("parsing brush");

			for (j = 0; j < 3; j++) {
				GetToken();
				planepts[i][j] = atof(parsedToken);
			}

			GetToken();
			if (*parsedToken != ')')
				Sys_Error("parsing brush");
		}

		/* read the texturedef */
		GetToken();
		if (strlen(parsedToken) >= MAX_TEXPATH) {
			if (config.performMapCheck || config.fixMap)
				Com_Printf("  ");/* hack to make this look like output from Check_Printf() */
			Com_Printf("ParseBrush: texture name too long (limit %i): %s\n", MAX_TEXPATH, parsedToken);
			if (config.fixMap)
				Sys_Error("Aborting, as -fix is active and saving might corrupt *.map by truncating texture name");
		}
		Q_strncpyz(td.name, parsedToken, sizeof(td.name));

		td.shift[0] = atof(GetToken());
		td.shift[1] = atof(GetToken());
		td.rotate = atof(GetToken());
		td.scale[0] = atof(GetToken());
		td.scale[1] = atof(GetToken());

		/* find default flags and values */
		const int mt = FindMiptex(td.name);
		side->surfaceFlags = td.surfaceFlags = side->contentFlags = td.value = 0;

		if (TokenAvailable()) {
			side->contentFlags = atoi(GetToken());
			side->surfaceFlags = td.surfaceFlags = atoi(GetToken());
			td.value = atoi(GetToken());
		}

		/* if in check or fix mode, let them choose to do this (with command line options),
		 * and then call is made elsewhere */
		if (!checkOrFix) {
			SetImpliedFlags(side, &td, b);
			/* if no other content flags are set - make this solid */
			if (!checkOrFix && side->contentFlags == 0)
				side->contentFlags = CONTENTS_SOLID;
		}

		/* translucent objects are automatically classified as detail and window */
		if (side->surfaceFlags & (SURF_BLEND33 | SURF_BLEND66 | SURF_ALPHATEST)) {
			side->contentFlags |= CONTENTS_DETAIL;
			side->contentFlags |= CONTENTS_TRANSLUCENT;
			side->contentFlags |= CONTENTS_WINDOW;
			side->contentFlags &= ~CONTENTS_SOLID;
		}
		if (config.fulldetail)
			side->contentFlags &= ~CONTENTS_DETAIL;
		if (!checkOrFix) {
			if (!(side->contentFlags & ((LAST_VISIBLE_CONTENTS - 1)
				| CONTENTS_ACTORCLIP | CONTENTS_WEAPONCLIP | CONTENTS_LIGHTCLIP)))
				side->contentFlags |= CONTENTS_SOLID;

			/* hints and skips are never detail, and have no content */
			if (side->surfaceFlags & (SURF_HINT | SURF_SKIP)) {
				side->contentFlags = 0;
				side->surfaceFlags &= ~CONTENTS_DETAIL;
			}
		}

		/* check whether the flags are ok */
		CheckFlags(side, b);

		/* generate a list of textures that should have footsteps when walking on them */
		if (mt > 0 && (side->surfaceFlags & SURF_FOOTSTEP))
			GenerateFootstepList(filename, mt);
		GenerateMaterialFile(filename, mt, side);

		/* find the plane number */
		int planenum = PlaneFromPoints(b, planepts[0], planepts[1], planepts[2]);
		if (planenum == PLANENUM_LEAF) {
			Com_Printf("Entity %i, Brush %i: plane with no normal\n", b->entitynum, b->brushnum);
			continue;
		}

		for (j = 0; j < 3; j++)
			VectorCopy(planepts[j], mapplanes[planenum].planeVector[j]);

		/* see if the plane has been used already */
		for (k = 0; k < b->numsides; k++) {
			const side_t* s2 = b->original_sides + k;
			if (s2->planenum == planenum) {
				Com_Printf("Entity %i, Brush %i: duplicate plane\n", b->entitynum, b->brushnum);
				break;
			}
			if (s2->planenum == (planenum ^ 1)) {
				Com_Printf("Entity %i, Brush %i: mirrored plane\n", b->entitynum, b->brushnum);
				break;
			}
		}
		if (k != b->numsides)
			continue;		/* duplicated */

		/* keep this side */
		side = b->original_sides + b->numsides;
		side->planenum = planenum;
		side->texinfo = TexinfoForBrushTexture(&mapplanes[planenum],
			&td, vec3_origin, side->contentFlags & CONTENTS_TERRAIN);
		side->brush = b;

		/* save the td off in case there is an origin brush and we
		 * have to recalculate the texinfo */
		side_brushtextures[nummapbrushsides] = td;

		Verb_Printf(VERB_DUMP, "Brush %i Side %i (%f %f %f) (%f %f %f) (%f %f %f) texinfo:%i[%s] plane:%i\n", nummapbrushes, nummapbrushsides,
			planepts[0][0], planepts[0][1], planepts[0][2],
			planepts[1][0], planepts[1][1], planepts[1][2],
			planepts[2][0], planepts[2][1], planepts[2][2],
			side->texinfo, td.name, planenum);

		nummapbrushsides++;
		b->numsides++;
	} while (1);

	/* get the content for the entire brush */
	b->contentFlags = BrushContents(b);

	/* copy all set face contentflags to the brush contentflags */
	for (int m = 0; m < b->numsides; m++)
		b->contentFlags |= b->original_sides[m].contentFlags;

	/* set DETAIL, TRANSLUCENT contentflags on all faces, if they have been set on any.
	 * called separately, if in check/fix mode */
	if (!checkOrFix)
		CheckPropagateParserContentFlags(b);

	/* allow detail brushes to be removed */
	if (config.nodetail && (b->contentFlags & CONTENTS_DETAIL)) {
		b->numsides = 0;
		return;
	}

	/* allow water brushes to be removed */
	if (config.nowater && (b->contentFlags & CONTENTS_WATER)) {
		b->numsides = 0;
		return;
	}

	/* create windings for sides and bounds for brush */
	MakeBrushWindings(b);

	Verb_Printf(VERB_DUMP, "Brush %i mins (%f %f %f) maxs (%f %f %f)\n", nummapbrushes,
		b->mbBox.mins[0], b->mbBox.mins[1], b->mbBox.mins[2],
		b->mbBox.maxs[0], b->mbBox.maxs[1], b->mbBox.maxs[2]);

	/* origin brushes are removed, but they set
	 * the rotation origin for the rest of the brushes (like func_door)
	 * in the entity. After the entire entity is parsed, the planenums
	 * and texinfos will be adjusted for the origin brush */
	if (!checkOrFix && (b->contentFlags & CONTENTS_ORIGIN)) {
		char string[32];
		vec3_t origin;

		if (num_entities == 1) {
			Sys_Error("Entity %i, Brush %i: origin brushes not allowed in world"
				, b->entitynum, b->brushnum);
			return;
		}

		b->mbBox.getCenter(origin);

		Com_sprintf(string, sizeof(string), "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
		SetKeyValue(&entities[b->entitynum], "origin", string);
		Verb_Printf(VERB_EXTRA, "Entity %i, Brush %i: set origin to %s\n", b->entitynum, b->brushnum, string);

		VectorCopy(origin, entities[b->entitynum].origin);

		/* don't keep this brush */
		b->numsides = 0;

		return;
	}

	if (!checkOrFix)
		AddBrushBevels(b);

	nummapbrushes++;
	mapent->numbrushes++;
}
Esempio n. 23
0
static void UI_KeyBindingNodeDraw (uiNode_t *node)
{
	static const int panelTemplate[] = {
		CORNER_SIZE, MID_SIZE, CORNER_SIZE,
		CORNER_SIZE, MID_SIZE, CORNER_SIZE,
		MARGE
	};
	const char *binding, *description, *command;
	int texX, texY;
	const float *textColor;
	const char *image;
	vec2_t pos;
	const char *font = UI_GetFontFromNode(node);
	const int bindingWidth = EXTRADATA(node).bindingWidth;
	const int descriptionWidth = node->size[0] - bindingWidth;
	vec2_t descriptionPos, descriptionSize;
	vec2_t bindingPos, bindingSize;

	if (node->state) {
		textColor = node->color;
		texX = TILE_SIZE;
		texY = 0;
	} else {
		textColor = node->color;
		texX = 0;
		texY = 0;
	}
	if (UI_HasFocus(node))
		textColor = node->selectedColor;

	UI_GetNodeAbsPos(node, pos);

	Vector2Set(descriptionSize, descriptionWidth, node->size[1]);
	Vector2Set(bindingSize, bindingWidth, node->size[1]);
	Vector2Set(descriptionPos, pos[0], pos[1]);
	Vector2Set(bindingPos, pos[0] + descriptionWidth + node->padding, pos[1]);

	image = UI_GetReferenceString(node, node->image);
	if (image) {
		UI_DrawPanel(descriptionPos, descriptionSize, image, texX, texY, panelTemplate);
		UI_DrawPanel(bindingPos, bindingSize, image, texX, texY, panelTemplate);
	}

	binding = UI_GetReferenceString(node, node->text);
	if (Q_strnull(binding))
		binding = _("NONE");

	/** @todo check that this is a keybinding value (with macro expansion) */
	command = node->text + 9;
	description = Cmd_GetCommandDesc(command);
	if (description[0] == '\0')
		description = command;

	R_Color(textColor);

	UI_DrawStringInBox(font, node->contentAlign,
		descriptionPos[0] + node->padding, descriptionPos[1] + node->padding,
		descriptionSize[0] - node->padding - node->padding, descriptionSize[1] - node->padding - node->padding,
		description, LONGLINES_PRETTYCHOP);

	UI_DrawStringInBox(font, node->contentAlign,
		bindingPos[0] + node->padding, bindingPos[1] + node->padding,
		bindingSize[0] - node->padding - node->padding, bindingSize[1] - node->padding - node->padding,
		binding, LONGLINES_PRETTYCHOP);

	R_Color(NULL);
}
Esempio n. 24
0
/**
 * @brief Draws the image node
 * @param[in] node The UI node to draw
 */
void uiImageNode::draw (uiNode_t* node)
{
	vec2_t size;
	vec2_t nodepos;
	const image_t* image;
	vec2_t imagepos;
	vec2_t nodesize;

	const char* imageName = UI_GetReferenceString(node, node->image);
	if (Q_strnull(imageName))
		return;

	image = UI_LoadImage(imageName);
	if (!image)
		return;

	/* mouse darken effect */
	/** @todo convert all pic using mousefx into button.
	 * @todo delete mousefx
	 */
#if 0
	if (node->mousefx && node->state) {
		vec4_t color;
		VectorScale(node->color, 0.8, color);
		color[3] = node->color[3];
		R_Color(color);
	}
#endif

	UI_GetNodeAbsPos(node, nodepos);
	Vector2Copy(node->box.size, nodesize);
	nodesize[0] -= node->padding + node->padding;
	if (nodesize[0] < 0)
		nodesize[0] = 0;
	nodesize[1] -= node->padding + node->padding;
	if (nodesize[1] < 0)
		nodesize[1] = 0;

	/** @todo code is duplicated in the ekg node code */
	if (node->box.size[0] && !node->box.size[1]) {
		const float scale = image->width / node->box.size[0];
		Vector2Set(size, node->box.size[0], image->height / scale);
	} else if (node->box.size[1] && !node->box.size[0]) {
		const float scale = image->height / node->box.size[1];
		Vector2Set(size, image->width / scale, node->box.size[1]);
	} else {
		Vector2Copy(nodesize, size);

		if (EXTRADATA(node).preventRatio) {
			/* maximize the image into the bounding box */
			const float ratio = (float) image->width / (float) image->height;
			if (size[1] * ratio > size[0]) {
				Vector2Set(size, size[0], size[0] / ratio);
			} else {
				Vector2Set(size, size[1] * ratio, size[1]);
			}
		}
	}

	UI_ImageAlignBoxInBox(nodepos, nodesize, size, (align_t) node->contentAlign, imagepos);
	UI_DrawNormImage(false, imagepos[0] + node->padding, imagepos[1] + node->padding, size[0], size[1],
			EXTRADATA(node).texh[0], EXTRADATA(node).texh[1],
			EXTRADATA(node).texl[0], EXTRADATA(node).texl[1], image);

	/** @todo convert all pic using mousefx into button.
	 * @todo delete mousefx
	 */
#if 0
	if (node->mousefx && node->state) {
		R_Color(nullptr);
	}
#endif
}
Esempio n. 25
0
/**
 * @sa M_Stop
 */
static void M_Start (const char* file)
{
	if (Q_strnull(file))
		return;

	if (!s_env.initialized) {
		Com_Printf("M_Start: No sound started!\n");
		return;
	}

	if (music.playingStream || !music.playing)
		return;

	char name[MAX_QPATH];
	Com_StripExtension(file, name, sizeof(name));
	const size_t len = strlen(name);
	if (len + 4 >= MAX_QPATH) {
		Com_Printf("M_Start: MAX_QPATH exceeded: " UFO_SIZE_T "\n", len + 4);
		return;
	}

	/* we are already playing that track */
	if (Q_streq(name, music.currentTrack) && music.data && Mix_PlayingMusic())
		return;

	/* we are still playing some background track - fade it out */
	if (music.data && Mix_PlayingMusic()) {
		if (!Mix_FadeOutMusic(1500))
			M_Stop();
		Q_strncpyz(music.nextTrack, name, sizeof(music.nextTrack));
		return;
	}

	/* make really sure the last track is closed and freed */
	M_Stop();

	/* load it in */
	byte* musicBuf;
	const int size = FS_LoadFile(va("music/%s.ogg", name), &musicBuf);
	if (size == -1) {
		Com_Printf("M_Start: Could not load '%s' background track!\n", name);
		return;
	}

	SDL_RWops* rw = SDL_RWFromMem(musicBuf, size);
	if (!rw) {
		Com_Printf("M_Start: Could not load music: 'music/%s'!\n", name);
		FS_FreeFile(musicBuf);
		return;
	}
#if SDL_VERSION_ATLEAST(2,0,0)
	music.data = Mix_LoadMUS_RW(rw, 1);
#else
	music.data = Mix_LoadMUS_RW(rw);
#endif
	if (!music.data) {
		Com_Printf("M_Start: Could not load music: 'music/%s' (%s)!\n", name, Mix_GetError());
		SDL_FreeRW(rw);
		FS_FreeFile(musicBuf);
		return;
	}

	Q_strncpyz(music.currentTrack, name, sizeof(music.currentTrack));
	music.buffer = musicBuf;
	if (Mix_FadeInMusic(music.data, 1, 1500) == -1)
		Com_Printf("M_Start: Could not play music: 'music/%s' (%s)!\n", name, Mix_GetError());
}
Esempio n. 26
0
TEST_F(WebApiTest, Auth)
{
	if (Q_strnull(user) || Q_strnull(password))
		return;
	ASSERT_TRUE(WEB_Auth(user, password));
}
Esempio n. 27
0
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;
}
Esempio n. 28
0
/**
 * @brief add a non-empty String attribute to the XML Node
 * @param[out] parent XML Node structure to add to
 * @param[in] name Name of the attribute
 * @param[in] value Value of the attribute
 * @note if the value is empty nothing will be added
 */
void XML_AddStringValue (xmlNode_t* parent, const char* name, const char* value)
{
	if (Q_strnull(value))
		return;
	XML_AddString(parent, name, value);
}