예제 #1
0
/**
 * @brief Build the forbidden list for the pathfinding (server side).
 * @param[in] team The team number if the list should be calculated from the eyes of that team. Use 0 to ignore team.
 * @param[in] movingActor The moving actor to build the forbidden list for. If this is an AI actor, everything other actor will be
 * included in the forbidden list - even the invisible ones. This is needed to ensure that they are not walking into each other
 * (civilians <=> aliens, aliens <=> civilians)
 * @sa G_MoveCalc
 * @sa Grid_CheckForbidden
 * @sa CL_BuildForbiddenList <- shares quite some code
 * @note This is used for pathfinding.
 * It is a list of where the selected unit can not move to because others are standing there already.
 */
static void G_BuildForbiddenList (int team, const edict_t *movingActor)
{
    edict_t *ent = NULL;
    int visMask;

    forbiddenListLength = 0;

    /* team visibility */
    if (team)
        visMask = G_TeamToVisMask(team);
    else
        visMask = TEAM_ALL;

    while ((ent = G_EdictsGetNextInUse(ent))) {
        /* Dead 2x2 unit will stop walking, too. */
        if (G_IsBlockingMovementActor(ent) && (G_IsAI(movingActor) || (ent->visflags & visMask))) {
            forbiddenList[forbiddenListLength++] = ent->pos;
            forbiddenList[forbiddenListLength++] = (byte*) &ent->fieldSize;
        } else if (ent->type == ET_SOLID) {
            int j;
            for (j = 0; j < ent->forbiddenListSize; j++) {
                forbiddenList[forbiddenListLength++] = ent->forbiddenListPos[j];
                forbiddenList[forbiddenListLength++] = (byte*) &ent->fieldSize;
            }
        }
    }

    if (forbiddenListLength > MAX_FORBIDDENLIST)
        gi.Error("G_BuildForbiddenList: list too long\n");
}
예제 #2
0
/**
 * @brief Let an actor fall down if e.g. the func_breakable the actor was standing on was destroyed.
 * @param[in,out] ent The actor that should fall down
 * @todo Handle cases where the grid position the actor would fall to is occupied by another actor already.
 */
void G_ActorFall (edict_t *ent)
{
    edict_t* entAtPos;
    const int oldZ = ent->pos[2];

    ent->pos[2] = gi.GridFall(gi.routingMap, ent->fieldSize, ent->pos);

    if (oldZ == ent->pos[2])
        return;

    entAtPos = G_GetEdictFromPos(ent->pos, ET_NULL);
    if (entAtPos != NULL && (G_IsBreakable(entAtPos) || G_IsBlockingMovementActor(entAtPos))) {
        const int diff = oldZ - ent->pos[2];
        G_TakeDamage(entAtPos, (int)(FALLING_DAMAGE_FACTOR * (float)diff));
    }

    G_EdictCalcOrigin(ent);
    gi.LinkEdict(ent);

    G_CheckVis(ent, true);

    G_EventActorFall(ent);

    gi.EndEvents();
}
예제 #3
0
/**
 * @brief Checks whether the actor should stop movement
 * @param ent The actors edict
 * @param visState The visibility check state @c VIS_PERISH, @c VIS_APPEAR
 * @return @c true if the actor should stop movement, @c false otherwise
 */
static bool G_ActorShouldStopInMidMove (const edict_t *ent, int visState, dvec_t* dvtab, int max)
{
    if (visState & VIS_STOP)
        return true;

    /* check that the appearing unit is not on a grid position the actor wanted to walk to.
     * this might be the case if the edict got visible in mid mode */
    if (visState & VIS_APPEAR) {
        pos3_t pos;
        VectorCopy(ent->pos, pos);
        while (max >= 0) {
            int tmp = 0;
            const edict_t *blockEdict;

            PosAddDV(pos, tmp, dvtab[max]);
            max--;
            blockEdict = G_GetLivingActorFromPos(pos);

            if (blockEdict && G_IsBlockingMovementActor(blockEdict)) {
                const bool visible = G_IsVisibleForTeam(blockEdict, ent->team);
                if (visible)
                    return true;
            }
        }
    }
    return false;
}
예제 #4
0
void G_ActorCheckRevitalise (Edict* ent)
{
	if (G_IsStunned(ent) && ent->STUN < ent->HP) {
		/* check that we could move after we stood up */
		Edict* otherActor = nullptr;
		while ((otherActor = G_EdictsGetNextInUse(otherActor))) {
			if (!VectorCompare(ent->pos, otherActor->pos))
				continue;
			if (G_IsBlockingMovementActor(otherActor))
				return;
		}

		G_ActorRevitalise(ent);
		G_EventActorRevitalise(*ent);
		G_SendStats(*ent);
	}
}