Esempio n. 1
0
/**
 * @brief Called every frame and checks whether a timed particle should be spawned
 */
static void CL_ParticleRunTimed (void)
{
	int i;
	const size_t length = lengthof(timedParticles);

	for (i = 0; i < length; i++) {
		timedParticle_t *tp = &timedParticles[i];
		if (!tp->parent || !tp->parent->inuse)
			continue;
		if (tp->n >= tp->max)
			continue;
		if (CL_Milliseconds() - tp->lastTime < tp->dt)
			continue;
		{
			ptl_t *p;
			if (!tp->n) {
				/* first spawn? - then copy the parent values. We have to
				 * do this here and now earlier because projectile particles
				 * get these values set after spawn. */
				VectorCopy(tp->parent->s, tp->s);
				VectorCopy(tp->parent->v, tp->v);
				VectorCopy(tp->parent->a, tp->a);
			}
			tp->n++;
			tp->lastTime = CL_Milliseconds();
			p = CL_ParticleSpawn(tp->ptl, tp->levelFlags, tp->s, tp->v, tp->a);
			if (p && tp->children) {
				p->next = tp->parent->children;
				p->parent = tp->parent;
				tp->parent->children = p;
			}
		}
	}
}
Esempio n. 2
0
static void CL_Reconnect (void)
{
	if (cls.reconnectTime == 0 || cls.reconnectTime > CL_Milliseconds())
		return;

	Com_Printf("Reconnecting...\n");
	CL_Disconnect();
	CL_SetClientState(ca_connecting);
	/* otherwise we would time out */
	cls.connectTime = CL_Milliseconds() - 1500;
}
Esempio n. 3
0
void uiTextEntryNode::draw (uiNode_t* node)
{
	const float* textColor;
	vec2_t pos;
	const char* font = UI_GetFontFromNode(node);
	uiSpriteStatus_t iconStatus = SPRITE_STATUS_NORMAL;

	if (node->disabled) {
		textColor = node->disabledColor;
		iconStatus = SPRITE_STATUS_DISABLED;
	} else if (node->state) {
		textColor = node->color;
		iconStatus = SPRITE_STATUS_HOVER;
	} else {
		textColor = node->color;
	}
	if (UI_HasFocus(node)) {
		textColor = node->selectedColor;
	}

	UI_GetNodeAbsPos(node, pos);

	if (EXTRADATA(node).background) {
		UI_DrawSpriteInBox(false, EXTRADATA(node).background, iconStatus, pos[0], pos[1], node->box.size[0], node->box.size[1]);
	}

	if (char const* const text = UI_GetReferenceString(node, node->text)) {
		char  buf[MAX_VAR];
		if (EXTRADATA(node).isPassword) {
			size_t size = UTF8_strlen(text);

			if (size > MAX_VAR - 2)
				size = MAX_VAR - 2;

			memset(buf, HIDECHAR, size);
			buf[size] = '\0';
		} else {
			/* leave one byte empty for the text-based cursor */
			UTF8_strncpyz(buf, text, sizeof(buf) - 1);
		}

		/** @todo Make the cursor into a real graphical object instead of using a text character. */
		if (UI_HasFocus(node)) {
			if (CL_Milliseconds() % 1000 < 500) {
				UTF8_insert_char_at(buf, sizeof(buf), EXTRADATA(node).cursorPosition, (int)CURSOR_ON);
			} else {
				UTF8_insert_char_at(buf, sizeof(buf), EXTRADATA(node).cursorPosition, (int)CURSOR_OFF);
			}
		}

		if (*buf != '\0') {
			R_Color(textColor);
			UI_DrawStringInBox(font, (align_t)node->contentAlign,
				pos[0] + node->padding, pos[1] + node->padding,
				node->box.size[0] - node->padding - node->padding, node->box.size[1] - node->padding - node->padding,
				buf);
			R_Color(nullptr);
		}
	}
}
Esempio n. 4
0
/**
 * @brief
 * @note Called after precache was sent from the server
 * @sa SV_Configstrings_f
 * @sa CL_Precache_f
 */
void CL_RequestNextDownload (void)
{
	if (cls.state != ca_connected) {
		Com_Printf("CL_RequestNextDownload: Not connected (%i)\n", cls.state);
		return;
	}

	/* Use the map data from the server */
	cl.mapTiles = SV_GetMapTiles();
	cl.mapData = SV_GetMapData();

	/* as a multiplayer client we have to load the map here and
	 * check the compatibility with the server */
	if (!Com_ServerState() && !CL_CanMultiplayerStart())
		return;

	CL_ViewLoadMedia();

	dbuffer msg(7);
	/* send begin */
	/* this will activate the render process (see client state ca_active) */
	NET_WriteByte(&msg, clc_stringcmd);
	/* see CL_StartGame */
	NET_WriteString(&msg, NET_STATE_BEGIN "\n");
	NET_WriteMsg(cls.netStream, msg);

	cls.waitingForStart = CL_Milliseconds();

	S_MumbleLink();
}
Esempio n. 5
0
/**
 * @note Only call @c CL_Connect if there is no connection yet (@c cls.netStream is @c nullptr)
 * @sa CL_Disconnect
 * @sa CL_SendChangedUserinfos
 */
static void CL_Connect (void)
{
	Com_SetUserinfoModified(false);

	assert(!cls.netStream);

	if (cls.servername[0] != '\0') {
		assert(cls.serverport[0] != '\0');
		Com_Printf("Connecting to %s %s...\n", cls.servername, cls.serverport);
		cls.netStream = NET_Connect(cls.servername, cls.serverport, CL_FreeClientStream);
	} else {
		Com_Printf("Connecting to localhost...\n");
		cls.netStream = NET_ConnectToLoopBack(CL_FreeClientStream);
	}

	if (cls.netStream) {
		char info[MAX_INFO_STRING];
		NET_OOB_Printf(cls.netStream, SV_CMD_CONNECT " %i \"%s\"\n", PROTOCOL_VERSION, Cvar_Userinfo(info, sizeof(info)));
		cls.connectTime = CL_Milliseconds();
	} else {
		if (cls.servername[0] != '\0') {
			assert(cls.serverport[0]);
			Com_Printf("Could not connect to %s %s\n", cls.servername, cls.serverport);
		} else {
			Com_Printf("Could not connect to localhost\n");
		}
	}
}
Esempio n. 6
0
/**
 * @sa CL_SendCommand
 */
void IN_SendKeyEvents (void)
{
	while (keyq_head != keyq_tail) {
		Key_Event(keyq[keyq_tail].key, keyq[keyq_tail].unicode, keyq[keyq_tail].down, CL_Milliseconds());
		keyq_tail = (keyq_tail + 1) & (MAX_KEYQ - 1);
	}
}
Esempio n. 7
0
/**
 * @brief Restart a timer
 */
void UI_TimerStart (uiTimer_t *timer)
{
	if (timer->isRunning)
		return;
	assert(ui_firstTimer != timer && timer->prev == nullptr && timer->next == nullptr);
	timer->nextTime = CL_Milliseconds() + timer->delay;
	timer->isRunning = true;
	UI_InsertTimerInActiveList(ui_firstTimer, timer);
}
Esempio n. 8
0
/**
 * @sa CL_Frame
 */
static void CL_SendCommand (void)
{
	/* get new key events */
	IN_SendKeyEvents();

	/* process console commands */
	Cbuf_Execute();

	/* send intentions now */
	CL_SendChangedUserinfos();

	/* fix any cheating cvars */
	Cvar_FixCheatVars();

	switch (cls.state) {
	case ca_disconnected:
		/* if the local server is running and we aren't connected then connect */
		if (Com_ServerState()) {
			cls.servername[0] = '\0';
			cls.serverport[0] = '\0';
			CL_SetClientState(ca_connecting);
			return;
		}
		break;
	case ca_connecting:
		if (CL_Milliseconds() - cls.connectTime > cl_connecttimeout->integer) {
			if (GAME_IsMultiplayer())
				Com_Error(ERR_DROP, "Server is not reachable");
		}
		break;
	case ca_connected:
		if (cls.waitingForStart) {
			if (CL_Milliseconds() - cls.waitingForStart > cl_connecttimeout->integer) {
				Com_Error(ERR_DROP, "Server aborted connection - the server didn't response in %is. You can try to increase the cvar cl_connecttimeout",
						cl_connecttimeout->integer / 1000);
			} else {
				SCR_DrawLoading(100);
			}
		}
		break;
	default:
		break;
	}
}
Esempio n. 9
0
static void UI_AbstractNodeCallDeleteTimed (uiNode_t* node, const uiCallContext_t* context)
{
	if (UI_GetParamNumber(context) != 1) {
		Com_Printf("UI_AbstractNodeCallDeleteTimed: Invalid number of parameters\n");
		return;
	}
	const char* msStr = UI_GetParam(context, 1);
	const int ms = atoi(msStr);
	if (ms <= 0) {
		UI_DeleteNode(node);
	} else {
		node->deleteTime = CL_Milliseconds() + ms;
	}
}
Esempio n. 10
0
/**
 * @brief This is called every frame, and can also be called explicitly to flush text to the screen
 * @sa UI_Draw
 * @sa CL_ViewRender
 * @sa SCR_DrawConsole
 * @sa SCR_DrawCursor
 */
void SCR_UpdateScreen (void)
{
	if (cls.waitingForStart)
		return;

	/* if the screen is disabled (loading plaque is up, or vid mode changing)
	 * do nothing at all */
	if (cls.disableScreen) {
		if (CL_Milliseconds() - cls.disableScreen > 120000 && refdef.ready) {
			cls.disableScreen = 0;
			Com_Printf("Loading plaque timed out.\n");
			return;
		}
	}

	/* not initialized yet */
	if (!screenInitialized)
		return;

	R_BeginFrame();

	/* draw scene, if it is need */
	CL_ViewRender();

	/* draw the ui on top of the render view */
	UI_Draw();

	SCR_DrawConsole();

	if (cl_fps->integer)
		SCR_DrawString(viddef.context.width - 20 - con_fontWidth * 10, 0, va("fps: %3.1f", cls.framerate));
	if (scr_rspeed->integer) {
		if (CL_OnBattlescape())
			SCR_DrawString(viddef.context.width - 20 - con_fontWidth * 30, 80, va("brushes: %6i alias: %6i\n", refdef.brushCount, refdef.aliasCount));
		else
			SCR_DrawString(viddef.context.width - 20 - con_fontWidth * 30, 80, va("alias: %6i\n", refdef.aliasCount));

		SCR_DrawString(viddef.context.width - 20 - con_fontWidth * 30, 80 + con_fontHeight, va("batches: %6i\n", refdef.batchCount));
		if (r_programs->integer) {
			SCR_DrawString(viddef.context.width - 20 - con_fontWidth * 30, 80 + con_fontHeight * 2, va("FFP->shader switches:    %6i\n", refdef.FFPToShaderCount));
			SCR_DrawString(viddef.context.width - 20 - con_fontWidth * 30, 80 + con_fontHeight * 3, va("shader->shader switches: %6i\n", refdef.shaderToShaderCount));
			SCR_DrawString(viddef.context.width - 20 - con_fontWidth * 30, 80 + con_fontHeight * 4, va("shader->FFP switches:    %6i\n", refdef.shaderToFFPCount));
		}
	}

	SCR_DrawCursor();

	R_EndFrame();
}
Esempio n. 11
0
/**
 * @brief Validates the parms and queues the sound up
 * @param[in] origin if this is @c nullptr, the sound will be dynamically sourced from the entity
 * @param[in] sample The soundfile to play
 * @param[in] atten Attenuation of sound to be played (for example, @c fireAttenuation
 * or @c impactAttenuation from @c fireDef_s).
 * @param[in] relVolume Max mixer volume factor (0.0 - 1.0)
 * @sa S_StartLocalSample
 * @sa S_SetVolume
 */
void S_PlaySample (const vec3_t origin, s_sample_t* sample, float atten, float relVolume)
{
	s_channel_t* ch;
	int i;
	float volume;

	if (!s_env.initialized)
		return;

	if (!sample)
		return;

	/* if the last mix of this particular sample is less than half a second ago, skip it */
	if (sample->lastPlayed > CL_Milliseconds() - s_env.sampleRepeatRate)
		return;

	if ((i = S_AllocChannel()) == -1)
		return;

	sample->lastPlayed = CL_Milliseconds();
	ch = &s_env.channels[i];

	ch->atten = atten;
	ch->sample = sample;

	if (origin != nullptr) {
		VectorCopy(origin, ch->org);
		S_SpatializeChannel(ch);
	}

	volume = snd_volume->value * relVolume * MIX_MAX_VOLUME;
	Com_DPrintf(DEBUG_SOUND, "%i: Playing sample '%s' at volume %f at channel %i\n",
			CL_Milliseconds(), sample->name, volume, i);
	Mix_VolumeChunk(ch->sample->chunk, volume);
	Mix_PlayChannel(i, ch->sample->chunk, 0);
}
Esempio n. 12
0
/**
 * @brief Adds a loop sample for e.g. ambient sounds
 */
void S_LoopSample (const vec3_t org, s_sample_t* sample, float relVolume, float attenuation)
{
	s_channel_t* ch;
	int i;

	if (!sample || !sample->chunk)
		return;

	ch = nullptr;

	for (i = 0; i < MAX_CHANNELS; i++){  /* find existing loop sound */
		if (s_env.channels[i].sample == sample) {
			vec3_t delta;
			VectorSubtract(s_env.channels[i].org, org, delta);
			if (VectorLength(delta) < 255.0) {
				ch = &s_env.channels[i];
				break;
			}
		}
	}

	if (ch) {  /* update existing loop sample */
		ch->count++;

		VectorMix(ch->org, org, 1.0 / ch->count, ch->org);
	} else {  /* or allocate a new one */
		float volume;

		if ((i = S_AllocChannel()) == -1)
			return;

		ch = &s_env.channels[i];

		sample->lastPlayed = CL_Milliseconds();
		VectorCopy(org, ch->org);
		ch->count = 1;
		ch->atten = attenuation;
		ch->sample = sample;

		volume = snd_volume->value * relVolume * MIX_MAX_VOLUME;
		Mix_VolumeChunk(ch->sample->chunk, volume);
		Mix_PlayChannel(i, ch->sample->chunk, 0);
	}

	S_SpatializeChannel(ch);
}
Esempio n. 13
0
/**
 * @brief Internal function to handle timers
 */
void UI_HandleTimers (void)
{
	/* is first element is out of date? */
	while (ui_firstTimer && ui_firstTimer->nextTime <= CL_Milliseconds()) {
		uiTimer_t *timer = ui_firstTimer;

		/* throw event */
		timer->calledTime++;
		timer->callback(timer->owner, timer);

		/* update the sorted list */
		if (timer->isRunning) {
			UI_RemoveTimerFromActiveList(timer);
			timer->nextTime += timer->delay;
			UI_InsertTimerInActiveList(timer->next, timer);
		}
	}
}
Esempio n. 14
0
/**
 * @brief Handles the catch of a @c kbutton_t state
 * @sa IN_KeyUp
 * @sa CL_GetKeyMouseState
 * @note Called from console callbacks with two parameters, the
 * key and the milliseconds when the key was released
 */
static void IN_KeyDown (kbutton_t * b)
{
	int k;
	const char *c = Cmd_Argv(1);

	if (c[0])
		k = atoi(c);
	else
		/* typed manually at the console for continuous down */
		k = -1;

	/* repeating key */
	if (k == b->down[0] || k == b->down[1])
		return;

	if (!b->down[0])
		b->down[0] = k;
	else if (!b->down[1])
		b->down[1] = k;
	else {
		Com_Printf("Three keys down for a button!\n");
		return;
	}

	/* still down */
	if (b->state)
		return;

	/* save timestamp */
	c = Cmd_Argv(2);
	b->downtime = atoi(c);
	if (!b->downtime)
		b->downtime = CL_Milliseconds() - 100;

	/* down */
	b->state = 1;
}
Esempio n. 15
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. 16
0
/**
 * @sa SCR_UpdateScreen
 * @sa SCR_EndLoadingPlaque
 * @sa SCR_DrawLoading
 */
void SCR_BeginLoadingPlaque (void)
{
	cls.disableScreen = CL_Milliseconds();
}
Esempio n. 17
0
static void UI_TextEntryNodeDraw (uiNode_t *node)
{
    static const int panelTemplate[] = {
        CORNER_SIZE, MID_SIZE, CORNER_SIZE,
        CORNER_SIZE, MID_SIZE, CORNER_SIZE,
        MARGE
    };
    const char *text;
    int texX, texY;
    const float *textColor;
    const char *image;
    vec2_t pos;
    static vec4_t disabledColor = {0.5, 0.5, 0.5, 1.0};
    const char *font = UI_GetFontFromNode(node);

    if (node->disabled) {
        /** @todo need custom color when node is disabled */
        textColor = disabledColor;
        texX = TILE_SIZE;
        texY = TILE_SIZE;
    } else 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);

    image = UI_GetReferenceString(node, node->image);
    if (image)
        UI_DrawPanel(pos, node->size, image, texX, texY, panelTemplate);

    text = UI_GetReferenceString(node, node->text);
    if (text != NULL) {
        /** @todo we don't need to edit the text to draw the cursor */
        if (UI_HasFocus(node)) {
            if (CL_Milliseconds() % 1000 < 500) {
                text = va("%s%c", text, CURSOR);
            }
        }

        if (EXTRADATA(node).isPassword) {
            char *c = va("%s", text);
            int size = UTF8_strlen(c);
            text = c;
            /* hide the text with a special char */
            assert(strlen(c) >= size);	/* trustable, but it can't be false */
            while (size) {
                *c++ = HIDECHAR;
                size--;
            }
            /* readd the cursor */
            if (UI_HasFocus(node)) {
                if (CL_Milliseconds() % 1000 < 500) {
                    c--;
                    *c++ = CURSOR;
                }
            }
            *c = '\0';
        }

        if (*text != '\0') {
            R_Color(textColor);
            UI_DrawStringInBox(font, node->textalign,
                               pos[0] + node->padding, pos[1] + node->padding,
                               node->size[0] - node->padding - node->padding, node->size[1] - node->padding - node->padding,
                               text, LONGLINES_PRETTYCHOP);
            R_Color(NULL);
        }
    }

}