/** * @brief Adds a box that highlights the current active door */ static void LE_AddEdictHighlight (const le_t* le) { const cBspModel_t* model = LE_GetClipModel(le); entity_t ent(RF_BOX); VectorSet(ent.color, 1, 1, 1); ent.alpha = (sin(cl.time * 6.28) + 1.0) / 2.0; CalculateMinsMaxs(le->angles, model->cbmBox, le->origin, ent.eBox); R_AddEntity(&ent); }
/** * @brief Returns a headnode that can be used for testing or clipping an * object of mins/maxs size. * Offset is filled in to contain the adjustment that must be added to the * testing object's origin to get a point to use with the returned hull. * @param[in] le The local entity to get the bmodel from * @param[out] tile The maptile the bmodel belongs, too * @param[out] rmaShift the shift vector in case of an RMA (needed for doors) * @param[out] angles The rotation of the entity (in case of bmodels) * @return The headnode for the local entity * @sa SV_HullForEntity */ static int32_t CL_HullForEntity (const le_t* le, int* tile, vec3_t rmaShift, vec3_t angles) { /* special case for bmodels */ if (le->contents & CONTENTS_SOLID) { const cBspModel_t* model = LE_GetClipModel(le); /* special value for bmodel */ if (!model) Com_Error(ERR_DROP, "CL_HullForEntity: Error - le with nullptr bmodel (%i)\n", le->type); *tile = model->tile; VectorCopy(le->angles, angles); VectorCopy(model->shift, rmaShift); return model->headnode; } else { /* might intersect, so do an exact clip */ *tile = 0; VectorCopy(vec3_origin, angles); VectorCopy(vec3_origin, rmaShift); return CM_HeadnodeForBox(cl.mapTiles->mapTiles[*tile], le->aabb); } }
/** * @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); } }