예제 #1
0
/**
 * @brief Searches a free spawning point for a given actor size and turns it into an actor
 * @param[in] player The player to get the free spawn points for
 * @param[in] actorSize The actor size to get a spawning point for
 * @return An actor edict or @c NULL if no free spawning point was found
 */
edict_t* G_ClientGetFreeSpawnPointForActorSize (const player_t *player, const actorSizeEnum_t actorSize)
{
	edict_t *ent;

	if (actorSize == ACTOR_SIZE_NORMAL) {
		/* Find valid actor spawn fields for this player. */
		ent = G_ClientGetFreeSpawnPoint(player, ET_ACTORSPAWN);
		if (ent) {
			edict_t *copy = G_EdictDuplicate(ent);
			if (copy != NULL)
				copy->type = ET_ACTOR;
			ent = copy;
		}
	} else if (actorSize == ACTOR_SIZE_2x2) {
		/* Find valid actor spawn fields for this player. */
		ent = G_ClientGetFreeSpawnPoint(player, ET_ACTOR2x2SPAWN);
		if (ent) {
			edict_t *copy = G_EdictDuplicate(ent);
			if (copy != NULL) {
				copy->type = ET_ACTOR2x2;
				copy->morale = 100;
			}
			ent = copy;
		}
	} else {
		gi.Error("G_ClientGetFreeSpawnPointForActorSize: unknown fieldSize for actor edict (actorSize: %i)\n",
				actorSize);
	}

	if (!ent)
		return NULL;

	level.num_spawned[ent->team]++;
	ent->pnum = player->num;
	ent->chr.fieldSize = actorSize;
	ent->fieldSize = ent->chr.fieldSize;
	ent->flags |= FL_DESTROYABLE;
	G_VisFlagsReset(ent);
	gi.LinkEdict(ent);

	if (ent->spawnflags & STATE_CROUCHED) {
		ent->think = G_ThinkActorGoCrouch;
		ent->nextthink = 1;
	}

	if (ent->spawnflags & STATE_STUN) {
		if (ent->spawnflags & STATE_DEAD)
			ent->HP = 0;
		ent->think = G_ThinkActorDieAfterSpawn;
		ent->nextthink = 1;
	}

	G_ActorModifyCounters(NULL, ent, 1, 0, 0);

	G_ReactionFireTargetsCreate(ent);

	return ent;
}
예제 #2
0
static bool G_InventoryPlaceItemAdjacent (edict_t *ent)
{
	vec2_t oldPos; /* if we have to place it to adjacent  */
	edict_t *floorAdjacent;
	int i;

	Vector2Copy(ent->pos, oldPos);
	floorAdjacent = NULL;

	for (i = 0; i < DIRECTIONS; i++) {
		/** @todo Check whether movement is possible here - otherwise don't use this field */
		/* extend pos with the direction vectors */
		/** @todo Don't know why the adjacent stuff has been disabled, but if it was buggy, it's probably */
		/** because the third ent->pos in the next line should be pos[1] ?!. (Duke, 13.1.11) */
		Vector2Set(ent->pos, ent->pos[0] + dvecs[i][0], ent->pos[0] + dvecs[i][1]);
		/* now try to get a floor entity for that new location */
		floorAdjacent = G_GetFloorItems(ent);
		if (!floorAdjacent) {
			floorAdjacent = G_SpawnFloor(ent->pos);
		} else {
			/* destroy this edict (send this event to all clients that see the edict) */
			G_EventPerish(floorAdjacent);
			G_VisFlagsReset(floorAdjacent);
		}

		INVSH_FindSpace(&floorAdjacent->i, &ic->item, INVDEF(gi.csi->idFloor), &x, &y, ic);
		if (x != NONE) {
			ic->x = x;
			ic->y = y;
			ic->next = FLOOR(floorAdjacent);
			FLOOR(floorAdjacent) = ic;
			break;
		}
		/* restore original pos */
		Vector2Copy(oldPos, ent->pos);
	}

	/* added to adjacent pos? */
	if (i < DIRECTIONS) {
		/* restore original pos - if no free space, this was done
		 * already in the for loop */
		Vector2Copy(oldPos, ent->pos);
		return false;
	}

	if (floorAdjacent)
		G_CheckVis(floorAdjacent, true);

	return true;
}
예제 #3
0
/**
 * @brief Move the whole given inventory to the floor and destroy the items that do not fit there.
 * @param[in] ent Pointer to an edict_t being an actor.
 * @sa G_ActorDie
 */
void G_InventoryToFloor (edict_t *ent)
{
	invList_t *ic, *next;
	containerIndex_t container;
	edict_t *floor;
	item_t item;

	/* check for items */
	for (container = 0; container < gi.csi->numIDs; container++) {
		/* ignore items linked from any temp container */
		if (INVDEF(container)->temp)
			continue;
		if (G_InventoryDropToFloorCheck(ent, container))
			break;
	}

	/* edict is not carrying any items */
	if (container >= gi.csi->numIDs)
		return;

	/* find the floor */
	floor = G_GetFloorItems(ent);
	if (!floor) {
		floor = G_SpawnFloor(ent->pos);
	} else {
		/* destroy this edict (send this event to all clients that see the edict) */
		G_EventPerish(floor);
		G_VisFlagsReset(floor);
	}

	/* drop items */
	/* cycle through all containers */
	for (container = 0; container < gi.csi->numIDs; container++) {
		/* skip floor - we want to drop to floor */
		if (container == gi.csi->idFloor)
			continue;

		/* skip csi->idArmour, we will collect armours using idArmour container,
		 * not idFloor */
		if (container == gi.csi->idArmour)
			continue;

		/* now cycle through all items for the container of the character (or the entity) */
		for (ic = CONTAINER(ent, container); ic; ic = next) {
			/* Save the next inv-list before it gets overwritten below.
			 * Do not put this in the "for" statement,
			 * unless you want an endless loop. ;) */
			next = ic->next;
			item = ic->item;

			/* only floor can summarize, so everything on the actor must have amount=1 */
			assert(item.amount == 1);
			if (!game.i.RemoveFromInventory(&game.i, &ent->chr.i, INVDEF(container), ic))
				gi.Error("Could not remove item '%s' from inventory %i of entity %i",
						ic->item.item->id, container, ent->number);
			if (game.i.AddToInventory(&game.i, &floor->chr.i, &item, INVDEF(gi.csi->idFloor), NONE, NONE, 1) == NULL)
				gi.Error("Could not add item '%s' from inventory %i of entity %i to floor container",
						ic->item.item->id, container, ent->number);
#ifdef ADJACENT
			G_InventoryPlaceItemAdjacent(ent);
#endif
		}
		/* destroy link */
		CONTAINER(ent, container) = NULL;
	}

	FLOOR(ent) = FLOOR(floor);

	/* send item info to the clients */
	G_CheckVis(floor);
}