00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "g_local.h"
00026
00032 edict_t *G_GetFloorItemsFromPos (const pos3_t pos)
00033 {
00034 return G_GetEdictFromPos(pos, ET_ITEM);
00035 }
00036
00043 edict_t *G_GetFloorItems (edict_t * ent)
00044 {
00045 edict_t *floor = G_GetFloorItemsFromPos(ent->pos);
00046
00047 if (floor) {
00048 FLOOR(ent) = FLOOR(floor);
00049 return floor;
00050 }
00051
00052
00053 FLOOR(ent) = NULL;
00054 return NULL;
00055 }
00056
00064 qboolean G_InventoryRemoveItemByID (const char *itemID, edict_t *ent, containerIndex_t container)
00065 {
00066 invList_t *ic = CONTAINER(ent, container);
00067 while (ic) {
00068 objDef_t *item = ic->item.t;
00069 if (item != NULL && !strcmp(item->id, itemID)) {
00070
00071 if (!game.i.RemoveFromInventory(&game.i, &ent->chr.i, INVDEF(container), ic))
00072 gi.Error("Could not remove item '%s' from inventory %i",
00073 ic->item.t->id, container);
00074 G_EventInventoryDelete(ent, G_VisToPM(ent->visflags), INVDEF(container), ic->x, ic->y);
00075 return qtrue;
00076 }
00077 ic = ic->next;
00078 }
00079
00080 return qfalse;
00081 }
00082
00090 static qboolean G_InventoryDropToFloorCheck (edict_t* ent, containerIndex_t container)
00091 {
00092 invList_t* ic = CONTAINER(ent, container);
00093
00094 if (container == gi.csi->idArmour)
00095 return qfalse;
00096
00097 if (ic) {
00098 qboolean check = qfalse;
00099 while (ic) {
00100 assert(ic->item.t);
00101 if (ic->item.t->isVirtual) {
00102 invList_t *next = ic->next;
00103
00104 if (!game.i.RemoveFromInventory(&game.i, &ent->chr.i, INVDEF(container), ic))
00105 gi.Error("Could not remove virtual item '%s' from inventory %i",
00106 ic->item.t->id, container);
00107 ic = next;
00108 } else {
00109
00110 check = qtrue;
00111 ic = ic->next;
00112 }
00113 }
00114 return check;
00115 }
00116
00117 return qfalse;
00118 }
00119
00125 qboolean G_AddItemToFloor (const pos3_t pos, const char *itemID)
00126 {
00127 edict_t *floor;
00128 item_t item = {NONE_AMMO, NULL, NULL, 0, 0};
00129 objDef_t *od = INVSH_GetItemByIDSilent(itemID);
00130 if (!od) {
00131 gi.DPrintf("Could not find item '%s'\n", itemID);
00132 return qfalse;
00133 }
00134
00135
00136 floor = G_GetFloorItemsFromPos(pos);
00137
00138 if (!floor)
00139 floor = G_SpawnFloor(pos);
00140
00141 item.t = od;
00142 return game.i.TryAddToInventory(&game.i, &floor->chr.i, item, INVDEF(gi.csi->idFloor));
00143 }
00144
00147
00148
00149 #ifdef ADJACENT
00150 static qboolean G_InventoryPlaceItemAdjacent (edict_t *ent)
00151 {
00152 vec2_t oldPos;
00153 edict_t *floorAdjacent;
00154 int i;
00155
00156 Vector2Copy(ent->pos, oldPos);
00157 floorAdjacent = NULL;
00158
00159 for (i = 0; i < DIRECTIONS; i++) {
00161
00162 Vector2Set(ent->pos, ent->pos[0] + dvecs[i][0], ent->pos[0] + dvecs[i][1]);
00163
00164 floorAdjacent = G_GetFloorItems(ent);
00165 if (!floorAdjacent) {
00166 floorAdjacent = G_SpawnFloor(ent->pos);
00167 } else {
00168
00169 G_EventPerish(floorAdjacent);
00170 floorAdjacent->visflags = 0;
00171 }
00172
00173 INVSH_FindSpace(&floorAdjacent->i, &ic->item, INVDEF(gi.csi->idFloor), &x, &y, ic);
00174 if (x != NONE) {
00175 ic->x = x;
00176 ic->y = y;
00177 ic->next = FLOOR(floorAdjacent);
00178 FLOOR(floorAdjacent) = ic;
00179 break;
00180 }
00181
00182 Vector2Copy(oldPos, ent->pos);
00183 }
00184
00185
00186 if (i < DIRECTIONS) {
00187
00188
00189 Vector2Copy(oldPos, ent->pos);
00190 return qfalse;
00191 }
00192
00193 if (floorAdjacent)
00194 G_CheckVis(floorAdjacent, qtrue);
00195
00196 return qtrue;
00197 }
00198 #endif
00199
00205 void G_InventoryToFloor (edict_t *ent)
00206 {
00207 invList_t *ic, *next;
00208 containerIndex_t container;
00209 edict_t *floor;
00210 item_t item;
00211
00212
00213 for (container = 0; container < gi.csi->numIDs; container++) {
00214
00215 if (INVDEF(container)->temp)
00216 continue;
00217 if (G_InventoryDropToFloorCheck(ent, container))
00218 break;
00219 }
00220
00221
00222 if (container >= gi.csi->numIDs)
00223 return;
00224
00225
00226 floor = G_GetFloorItems(ent);
00227 if (!floor) {
00228 floor = G_SpawnFloor(ent->pos);
00229 } else {
00230
00231 G_EventPerish(floor);
00232 floor->visflags = 0;
00233 }
00234
00235
00236
00237 for (container = 0; container < gi.csi->numIDs; container++) {
00238
00239 if (container == gi.csi->idFloor)
00240 continue;
00241
00242
00243
00244 if (container == gi.csi->idArmour)
00245 continue;
00246
00247
00248 for (ic = CONTAINER(ent, container); ic; ic = next) {
00249
00250
00251
00252 next = ic->next;
00253 item = ic->item;
00254
00255
00256 assert(item.amount == 1);
00257 if (!game.i.RemoveFromInventory(&game.i, &ent->chr.i, INVDEF(container), ic))
00258 gi.Error("Could not remove item '%s' from inventory %i of entity %i",
00259 ic->item.t->id, container, ent->number);
00260 if (game.i.AddToInventory(&game.i, &floor->chr.i, item, INVDEF(gi.csi->idFloor), NONE, NONE, 1) == NULL)
00261 gi.Error("Could not add item '%s' from inventory %i of entity %i to floor container",
00262 ic->item.t->id, container, ent->number);
00263 #ifdef ADJACENT
00264 G_InventoryPlaceItemAdjacent(ent);
00265 #endif
00266 }
00267
00268 CONTAINER(ent, container) = NULL;
00269 }
00270
00271 FLOOR(ent) = FLOOR(floor);
00272
00273
00274 G_CheckVis(floor, qtrue);
00275 }
00276
00286 void G_ReadItem (item_t *item, invDef_t **container, int *x, int *y)
00287 {
00288 int t, m;
00289 containerIndex_t containerID;
00290
00291 gi.ReadFormat("sbsbbbbs", &t, &item->a, &m, &containerID, x, y, &item->rotated, &item->amount);
00292
00293 if (t < 0 || t >= gi.csi->numODs)
00294 gi.Error("Item index out of bounds: %i", t);
00295 item->t = &gi.csi->ods[t];
00296
00297 if (m != NONE) {
00298 if (m < 0 || m >= gi.csi->numODs)
00299 gi.Error("Ammo index out of bounds: %i", m);
00300 item->m = &gi.csi->ods[m];
00301 } else {
00302 item->m = NULL;
00303 }
00304
00305 if (containerID >= 0 && containerID < gi.csi->numIDs)
00306 *container = INVDEF(containerID);
00307 else
00308 gi.Error("container id is out of bounds: %i", containerID);
00309 }
00310
00320 void G_WriteItem (const item_t *item, const invDef_t *container, int x, int y)
00321 {
00322 assert(item);
00323 assert(item->t);
00324 gi.WriteFormat("sbsbbbbs", item->t->idx, item->a, item->m ? item->m->idx : NONE, container->id, x, y, item->rotated, item->amount);
00325 }
00326
00334 void G_SendInventory (unsigned int playerMask, const edict_t *ent)
00335 {
00336 invList_t *ic;
00337 int nr = 0;
00338 containerIndex_t container;
00339
00340
00341 if (!playerMask)
00342 return;
00343
00344 for (container = 0; container < gi.csi->numIDs; container++) {
00345 for (ic = CONTAINER(ent, container); ic; ic = ic->next)
00346 nr++;
00347 }
00348
00349
00350 if (nr == 0)
00351 return;
00352
00353 G_EventInventoryAdd(ent, playerMask, nr);
00354 for (container = 0; container < gi.csi->numIDs; container++) {
00355 for (ic = CONTAINER(ent, container); ic; ic = ic->next) {
00356
00357 assert(ic->item.t);
00358 G_WriteItem(&ic->item, INVDEF(container), ic->x, ic->y);
00359 }
00360 }
00361 }