Beispiel #1
0
/**
 * @brief Callback for EV_DOOR_CLOSE event - rotates the inline model and recalc routing
 * @sa EV_DOOR_CLOSE
 * @sa G_ClientUseEdict
 * @sa Touch_DoorTrigger
 */
void CL_DoorClose (const eventRegister_t *self, struct dbuffer *msg)
{
    /* get local entity */
    int number;
    le_t *le;

    NET_ReadFormat(msg, self->formatString, &number);

    le = LE_Get(number);
    if (!le)
        LE_NotFoundError(number);

    if (le->type == ET_DOOR) {
        if (le->dir & DOOR_OPEN_REVERSE)
            le->angles[le->dir & 3] += DOOR_ROTATION_ANGLE;
        else
            le->angles[le->dir & 3] -= DOOR_ROTATION_ANGLE;

        CM_SetInlineModelOrientation(cl.mapTiles, le->inlineModelName, le->origin, le->angles);
        CL_RecalcRouting(le);
    } else if (le->type == ET_DOOR_SLIDING) {
        LE_SetThink(le, LET_DoorSlidingClose);
        le->think(le);
    } else {
        Com_Error(ERR_DROP, "Invalid door entity found of type: %i", le->type);
    }
}
Beispiel #2
0
/**
 * @brief Slides a door
 *
 * @note Though doors, sliding doors need a very different handling:
 * because it's movement is animated (unlike the rotating door),
 * the final position that is used to calculate the routing data
 * is set once the animation finished (because this recalculation
 * might be very expensive).
 *
 * @param[in,out] le The local entity of the inline model
 * @param[in] speed The speed to slide with - a negative value to close the door
 * @sa Door_SlidingUse
 */
void LET_SlideDoor (le_t* le, int speed)
{
	vec3_t moveAngles, moveDir;

	/* get the movement angle vector */
	GET_SLIDING_DOOR_SHIFT_VECTOR(le->dir, speed, moveAngles);

	/* this origin is only an offset to the absolute mins/maxs for rendering */
	VectorAdd(le->origin, moveAngles, le->origin);

	/* get the direction vector from the movement angles that were set on the entity */
	AngleVectors(moveAngles, moveDir, nullptr, nullptr);
	moveDir[0] = fabsf(moveDir[0]);
	moveDir[1] = fabsf(moveDir[1]);
	moveDir[2] = fabsf(moveDir[2]);
	/* calculate the distance from the movement angles and the entity size */
	const int distance = DotProduct(moveDir, le->size);

	bool endPos = false;
	if (speed > 0) {
		/* check whether the distance the door may slide is slided already
		 * - if so, stop the movement of the door */
		if (fabs(le->origin[le->dir & 3]) >= distance)
			endPos = true;
	} else {
		/* the sliding door has not origin set - except when it is opened. This door type is no
		 * origin brush based bmodel entity. So whenever the origin vector is not the zero vector,
		 * the door is opened. */
		if (VectorEmpty(le->origin))
			endPos = true;
	}

	if (endPos) {
		vec3_t distanceVec;
		/* the door finished its move - either close or open, so make sure to recalc the routing
		 * data and set the mins/maxs for the inline brush model */
		cBspModel_t* model = CM_InlineModel(cl.mapTiles, le->inlineModelName);

		assert(model);

		/* we need the angles vector normalized */
		GET_SLIDING_DOOR_SHIFT_VECTOR(le->dir, (speed < 0) ? -1 : 1, moveAngles);

		/* the bounding box of the door is updated in one step - here is no lerping needed */
		VectorMul(distance, moveAngles, distanceVec);

		model->cbmBox.shift(distanceVec);
		CL_RecalcRouting(le);

		/* reset the think function as the movement finished */
		LE_SetThink(le, nullptr);
	} else
		le->thinkDelay = 1000;
}
/**
 * @note e.g. func_breakable or func_door with health
 * @sa EV_MODEL_EXPLODE
 */
void CL_Explode (const eventRegister_t *self, struct dbuffer *msg)
{
	const int entnum = NET_ReadShort(msg);
	le_t *le = LE_Get(entnum);
	if (!le)
		LE_NotFoundError(entnum);

	le->inuse = false;
	if (le->modelnum1 > 0)
		cl.model_clip[le->modelnum1] = NULL;

	/* Recalc the client routing table because this le (and the inline model) is now gone */
	CL_RecalcRouting(le);
}
Beispiel #4
0
/**
 * @brief Rotates a door in the given speed
 *
 * @param[in] le The local entity of the door to rotate
 * @param[in] speed The speed to rotate the door with
 */
void LET_RotateDoor (le_t* le, int speed)
{
	/** @todo lerp the rotation */
	const int angle = speed > 0 ? DOOR_ROTATION_ANGLE : -DOOR_ROTATION_ANGLE;
	if (le->dir & DOOR_OPEN_REVERSE)
		le->angles[le->dir & 3] -= angle;
	else
		le->angles[le->dir & 3] += angle;

	CM_SetInlineModelOrientation(cl.mapTiles, le->inlineModelName, le->origin, le->angles);
	CL_RecalcRouting(le);

	/* reset the think function as the movement finished */
	LE_SetThink(le, nullptr);
}
Beispiel #5
0
/**
 * @brief Register local entities for SOLID_BSP models like func_breakable or func_door
 * @note func_breakable, func_door
 * @sa G_SendEdictsAndBrushModels
 * @sa EV_ADD_BRUSH_MODEL
 * @sa CL_SpawnParseEntitystring
 */
void CL_AddBrushModel (const eventRegister_t *self, struct dbuffer *msg)
{
	le_t *le;
	int entnum, modelnum1, levelflags, speed, dir;
	entity_type_t type;
	const cBspModel_t *model;
	int angle;
	vec3_t origin, angles;

	NET_ReadFormat(msg, self->formatString, &type, &entnum, &modelnum1, &levelflags, &origin, &angles, &speed, &angle, &dir);

	if (type != ET_BREAKABLE && type != ET_DOOR && type != ET_ROTATING && type != ET_DOOR_SLIDING && type != ET_TRIGGER_RESCUE && type != ET_TRIGGER_NEXTMAP)
		Com_Error(ERR_DROP, "Invalid le announced via EV_ADD_BRUSH_MODEL type: %i\n", type);
	else if (modelnum1 > MAX_MODELS || modelnum1 < 1)
		Com_Error(ERR_DROP, "Invalid le modelnum1 announced via EV_ADD_BRUSH_MODEL\n");

	/* check if the ent is already visible */
	le = LE_Get(entnum);
	if (le)
		Com_Error(ERR_DROP, "le announced a second time - le for entnum %i (type: %i) already exists (via EV_ADD_BRUSH_MODEL)\n", entnum, type);

	le = LE_Add(entnum);
	assert(le);

	le->rotationSpeed = speed / 100.0f;
	le->slidingSpeed = speed;
	le->angle = angle;
	le->dir = dir;
	le->type = type;
	le->modelnum1 = modelnum1;
	le->levelflags = levelflags;
	le->addFunc = LE_BrushModelAction;
	LE_SetThink(le, LET_BrushModel);
	/* The origin and angles are REQUIRED for doors to work! */
	VectorCopy(origin, le->origin);
	/* store the initial position - needed for sliding doors */
	VectorCopy(le->origin, le->oldOrigin);
	VectorCopy(angles, le->angles);

	Com_sprintf(le->inlineModelName, sizeof(le->inlineModelName), "*%i", le->modelnum1);
	model = LE_GetClipModel(le);
	le->model1 = R_FindModel(le->inlineModelName);
	if (!le->model1)
		Com_Error(ERR_DROP, "CL_AddBrushModel: Could not register inline model %i", le->modelnum1);

	/* Transfer model mins and maxs to entity */
	VectorCopy(model->mins, le->mins);
	VectorCopy(model->maxs, le->maxs);
	VectorSubtract(le->maxs, le->mins, le->size);
	VecToPos(le->origin, le->pos);

	/* to allow tracing against this le */
	if (!LE_IsNotSolid(le)) {
		/* This is to help the entity collision code out */
		/* Copy entity origin and angles to model*/
		CM_SetInlineModelOrientation(cl.mapTiles, le->inlineModelName, le->origin, le->angles);

		le->contents = CONTENTS_SOLID;

		CL_RecalcRouting(le);
	}
}