void CollideAllItems( const TTileItem *item, const Vec2i pos, const int mask, const CollisionTeam team, const bool isPVP, CollideItemFunc func, void *data) { const Vec2i tv = Vec2iToTile(pos); Vec2i dv; // Check collisions with all other items on this tile, in all 8 directions for (dv.y = -1; dv.y <= 1; dv.y++) { for (dv.x = -1; dv.x <= 1; dv.x++) { const Vec2i dtv = Vec2iAdd(tv, dv); if (!MapIsTileIn(&gMap, dtv)) { continue; } CArray *tileThings = &MapGetTile(&gMap, dtv)->things; for (int i = 0; i < (int)tileThings->size; i++) { TTileItem *ti = ThingIdGetTileItem(CArrayGet(tileThings, i)); // Don't collide if items are on the same team if (!CollisionIsOnSameTeam(ti, team, isPVP)) { if (item != ti && (ti->flags & mask) && ItemsCollide(item, ti, pos)) { func(ti, data); } } } } } }
static void DrawWallsAndThings(DrawBuffer *b, Vec2i offset) { Vec2i pos; Tile *tile = &b->tiles[0][0]; pos.y = b->dy + cWallOffset.dy + offset.y; for (int y = 0; y < Y_TILES; y++, pos.y += TILE_HEIGHT) { CArrayClear(&b->displaylist); pos.x = b->dx + cWallOffset.dx + offset.x; for (int x = 0; x < b->Size.x; x++, tile++, pos.x += TILE_WIDTH) { if (tile->flags & MAPTILE_IS_WALL) { if (!(tile->flags & MAPTILE_DELAY_DRAW)) { DrawWallColumn(y, pos, tile); } } else if (tile->flags & MAPTILE_OFFSET_PIC) { // Drawing doors // Doors may be offset; vertical doors are drawn centered // horizontal doors are bottom aligned Vec2i doorPos = pos; doorPos.x += (TILE_WIDTH - tile->picAlt->pic.size.x) / 2; if (tile->picAlt->pic.size.y > 16) { doorPos.y += TILE_HEIGHT - (tile->picAlt->pic.size.y % TILE_HEIGHT); } BlitMasked( &gGraphicsDevice, &tile->picAlt->pic, doorPos, GetTileLOSMask(tile), 0); } // Draw the items that are in LOS if (tile->flags & MAPTILE_OUT_OF_SIGHT) { continue; } CA_FOREACH(ThingId, tid, tile->things) const TTileItem *ti = ThingIdGetTileItem(tid); // Don't draw debris, they are drawn later if (TileItemIsDebris(ti)) { continue; } CArrayPushBack(&b->displaylist, &ti); CA_FOREACH_END() } DrawBufferSortDisplayList(b); CA_FOREACH(const TTileItem *, tp, b->displaylist) DrawThing(b, *tp, offset); CA_FOREACH_END() tile += X_TILES - b->Size.x; } }
TTileItem *GetItemOnTileInCollision( TTileItem *item, Vec2i pos, int mask, CollisionTeam team, int isDogfight) { Vec2i tv = Vec2iToTile(pos); Vec2i dv; if (!MapIsTileIn(&gMap, tv)) { return NULL; } // Check collisions with all other items on this tile, in all 8 directions for (dv.y = -1; dv.y <= 1; dv.y++) { for (dv.x = -1; dv.x <= 1; dv.x++) { CArray *tileThings = &MapGetTile(&gMap, Vec2iAdd(tv, dv))->things; for (int i = 0; i < (int)tileThings->size; i++) { TTileItem *ti = ThingIdGetTileItem(CArrayGet(tileThings, i)); // Don't collide if items are on the same team if (!CollisionIsOnSameTeam(ti, team, isDogfight)) { if (item != ti && (ti->flags & mask) && ItemsCollide(item, ti, pos)) { return ti; } } } } } return NULL; }
static void DrawDebris(DrawBuffer *b, Vec2i offset) { Tile *tile = &b->tiles[0][0]; for (int y = 0; y < Y_TILES; y++) { CArrayClear(&b->displaylist); for (int x = 0; x < b->Size.x; x++, tile++) { if (tile->flags & MAPTILE_OUT_OF_SIGHT) { continue; } CA_FOREACH(ThingId, tid, tile->things) const TTileItem *ti = ThingIdGetTileItem(tid); if (TileItemIsDebris(ti)) { CArrayPushBack(&b->displaylist, &ti); } CA_FOREACH_END() } DrawBufferSortDisplayList(b); CA_FOREACH(const TTileItem *, tp, b->displaylist) DrawThing(b, *tp, offset); CA_FOREACH_END() tile += X_TILES - b->Size.x; } }
static void DrawObjectNames(DrawBuffer *b, const Vec2i offset) { const Tile *tile = &b->tiles[0][0]; for (int y = 0; y < Y_TILES; y++) { for (int x = 0; x < b->Size.x; x++, tile++) { CA_FOREACH(ThingId, tid, tile->things) const TTileItem *ti = ThingIdGetTileItem(tid); if (ti->flags & TILEITEM_OBJECTIVE) { DrawObjectiveName(ti, b, offset); } else if (ti->kind == KIND_OBJECT) { const TObject *obj = CArrayGet(&gObjs, ti->id); if (obj->Class->Type == MAP_OBJECT_TYPE_PICKUP_SPAWNER) { DrawSpawnerName(obj, b, offset); } } CA_FOREACH_END() } tile += X_TILES - b->Size.x; } }
static void DrawObjectiveHighlights(DrawBuffer *b, Vec2i offset) { Tile *tile = &b->tiles[0][0]; for (int y = 0; y < Y_TILES; y++) { for (int x = 0; x < b->Size.x; x++, tile++) { // Draw the items that are in LOS CA_FOREACH(ThingId, tid, tile->things) TTileItem *ti = ThingIdGetTileItem(tid); DrawObjectiveHighlight(ti, tile, b, offset); CA_FOREACH_END() } tile += X_TILES - b->Size.x; } }
static void DrawObjectiveCompass( GraphicsDevice *g, Vec2i playerPos, Rect2i r, bool showExit) { // Draw exit position if (showExit) { DrawCompassArrow( g, r, MapGetExitPos(&gMap), playerPos, colorGreen, "Exit"); } // Draw objectives Map *map = &gMap; Vec2i tilePos; for (tilePos.y = 0; tilePos.y < map->Size.y; tilePos.y++) { for (tilePos.x = 0; tilePos.x < map->Size.x; tilePos.x++) { Tile *tile = MapGetTile(map, tilePos); for (int i = 0; i < (int)tile->things.size; i++) { TTileItem *ti = ThingIdGetTileItem(CArrayGet(&tile->things, i)); if (!(ti->flags & TILEITEM_OBJECTIVE)) { continue; } int objective = ObjectiveFromTileItem(ti->flags); MissionObjective *mo = CArrayGet(&gMission.missionData->Objectives, objective); if (mo->Flags & OBJECTIVE_HIDDEN) { continue; } if (!(mo->Flags & OBJECTIVE_POSKNOWN) && !tile->isVisited) { continue; } const ObjectiveDef *o = CArrayGet(&gMission.Objectives, objective); color_t color = o->color; DrawCompassArrow( g, r, Vec2iNew(ti->x, ti->y), playerPos, color, NULL); } } } }
static void DrawObjectiveHighlights(DrawBuffer *b, Vec2i offset) { Tile *tile = &b->tiles[0][0]; for (int y = 0; y < Y_TILES; y++) { for (int x = 0; x < b->Size.x; x++, tile++) { // Draw the items that are in LOS for (int i = 0; i < (int)tile->things.size; i++) { TTileItem *ti = ThingIdGetTileItem(CArrayGet(&tile->things, i)); DrawObjectiveHighlight(ti, tile, b, offset); } } tile += X_TILES - b->Size.x; } }
void DrawChatters(DrawBuffer *b, const Vec2i offset) { const Tile *tile = &b->tiles[0][0]; for (int y = 0; y < Y_TILES; y++) { for (int x = 0; x < b->Size.x; x++, tile++) { CA_FOREACH(ThingId, tid, tile->things) const TTileItem *ti = ThingIdGetTileItem(tid); if (ti->kind != KIND_CHARACTER) { continue; } DrawChatter(ti, b, offset); CA_FOREACH_END() } tile += X_TILES - b->Size.x; } }
static void DrawChatters(DrawBuffer *b, Vec2i offset) { const Tile *tile = &b->tiles[0][0]; for (int y = 0; y < Y_TILES; y++) { for (int x = 0; x < b->Size.x; x++, tile++) { CA_FOREACH(ThingId, tid, tile->things) const TTileItem *ti = ThingIdGetTileItem(tid); if (ti->getActorPicsFunc == NULL) { continue; } DrawChatter(ti, b, offset); CA_FOREACH_END() } tile += X_TILES - b->Size.x; } }
void DrawObjectiveHighlights(DrawBuffer *b, const Vec2i offset) { if (!ConfigGetBool(&gConfig, "Graphics.ShowHUD")) { return; } Tile *tile = &b->tiles[0][0]; for (int y = 0; y < Y_TILES; y++) { for (int x = 0; x < b->Size.x; x++, tile++) { // Draw the items that are in LOS CA_FOREACH(ThingId, tid, tile->things) TTileItem *ti = ThingIdGetTileItem(tid); DrawObjectiveHighlight(ti, tile, b, offset); CA_FOREACH_END() } tile += X_TILES - b->Size.x; } }
static void DrawDebris(DrawBuffer *b, Vec2i offset) { Tile *tile = &b->tiles[0][0]; for (int y = 0; y < Y_TILES; y++) { TTileItem *displayList = NULL; for (int x = 0; x < b->Size.x; x++, tile++) { if (tile->flags & MAPTILE_OUT_OF_SIGHT) { continue; } for (int i = 0; i < (int)tile->things.size; i++) { TTileItem *ti = ThingIdGetTileItem(CArrayGet(&tile->things, i)); if (ti->flags & TILEITEM_IS_WRECK) { AddItemToDisplayList(ti, &displayList); } } } for (TTileItem *t = displayList; t; t = t->nextToDisplay) { Vec2i pos = Vec2iNew( t->x - b->xTop + offset.x, t->y - b->yTop + offset.y); if (t->getPicFunc) { Vec2i picOffset; const Pic *pic = t->getPicFunc(t->id, &picOffset); Blit(&gGraphicsDevice, pic, Vec2iAdd(pos, picOffset)); } else { (*(t->drawFunc))(pos, &t->drawData); } } tile += X_TILES - b->Size.x; } }
static void DrawWallsAndThings(DrawBuffer *b, Vec2i offset) { Vec2i pos; Tile *tile = &b->tiles[0][0]; pos.y = b->dy + cWallOffset.dy + offset.y; for (int y = 0; y < Y_TILES; y++, pos.y += TILE_HEIGHT) { TTileItem *displayList = NULL; pos.x = b->dx + cWallOffset.dx + offset.x; for (int x = 0; x < b->Size.x; x++, tile++, pos.x += TILE_WIDTH) { if (tile->flags & MAPTILE_IS_WALL) { if (!(tile->flags & MAPTILE_DELAY_DRAW)) { DrawWallColumn(y, pos, tile); } } else if (tile->flags & MAPTILE_OFFSET_PIC) { // Drawing doors BlitMasked( &gGraphicsDevice, &tile->picAlt, pos, GetTileLOSMask(tile), 0); } if (!(tile->flags & MAPTILE_OUT_OF_SIGHT)) { // Draw the items that are in LOS for (int i = 0; i < (int)tile->things.size; i++) { TTileItem *ti = ThingIdGetTileItem(CArrayGet(&tile->things, i)); if (!(ti->flags & TILEITEM_IS_WRECK)) { AddItemToDisplayList(ti, &displayList); } } } } for (TTileItem *t = displayList; t; t = t->nextToDisplay) { Vec2i picPos = Vec2iNew( t->x - b->xTop + offset.x, t->y - b->yTop + offset.y); if (t->getPicFunc) { Vec2i picOffset; const Pic *pic = t->getPicFunc(t->id, &picOffset); Blit(&gGraphicsDevice, pic, Vec2iAdd(picPos, picOffset)); } else if (t->getActorPicsFunc) { ActorPics pics = t->getActorPicsFunc(t->id); if (pics.IsDead) { if (pics.IsDying) { int pic = pics.OldPics[0]; if (pic == 0) { continue; } if (pics.IsTransparent) { DrawBTPic( &gGraphicsDevice, PicManagerGetFromOld(&gPicManager, pic), Vec2iAdd(picPos, pics.Pics[0].offset), pics.Tint); } else { DrawTTPic( picPos.x + pics.Pics[0].offset.x, picPos.y + pics.Pics[0].offset.y, PicManagerGetOldPic(&gPicManager, pic), pics.Table); } } } else if (pics.IsTransparent) { for (int i = 0; i < 3; i++) { Pic *oldPic = PicManagerGetFromOld( &gPicManager, pics.OldPics[i]); if (oldPic == NULL) { continue; } DrawBTPic( &gGraphicsDevice, oldPic, Vec2iAdd(picPos, pics.Pics[i].offset), pics.Tint); } } else { DrawShadow(&gGraphicsDevice, picPos, Vec2iNew(8, 6)); for (int i = 0; i < 3; i++) { PicPaletted *oldPic = PicManagerGetOldPic( &gPicManager, pics.OldPics[i]); if (oldPic == NULL) { continue; } BlitOld( picPos.x + pics.Pics[i].offset.x, picPos.y + pics.Pics[i].offset.y, oldPic, pics.Table, BLIT_TRANSPARENT); } } } else { (*(t->drawFunc))(picPos, &t->drawData); } } tile += X_TILES - b->Size.x; } }
static void DrawWallsAndThings(DrawBuffer *b, Vec2i offset) { Vec2i pos; Tile *tile = &b->tiles[0][0]; pos.y = b->dy + WALL_OFFSET_Y + offset.y; const bool useFog = ConfigGetBool(&gConfig, "Game.Fog"); for (int y = 0; y < Y_TILES; y++, pos.y += TILE_HEIGHT) { CArrayClear(&b->displaylist); pos.x = b->dx + offset.x; for (int x = 0; x < b->Size.x; x++, tile++, pos.x += TILE_WIDTH) { if (tile->flags & MAPTILE_IS_WALL) { if (!(tile->flags & MAPTILE_DELAY_DRAW)) { DrawWallColumn(y, pos, tile); } } else if (tile->flags & MAPTILE_OFFSET_PIC) { // Drawing doors // Doors may be offset; vertical doors are drawn centered // horizontal doors are bottom aligned Vec2i doorPos = pos; doorPos.x += (TILE_WIDTH - tile->picAlt->pic.size.x) / 2; if (tile->picAlt->pic.size.y > 16) { doorPos.y += TILE_HEIGHT - (tile->picAlt->pic.size.y % TILE_HEIGHT); } switch (GetTileLOS(tile, useFog)) { case TILE_LOS_NORMAL: Blit(&gGraphicsDevice, &tile->picAlt->pic, doorPos); break; case TILE_LOS_FOG: BlitMasked( &gGraphicsDevice, &tile->picAlt->pic, doorPos, colorFog, false); break; case TILE_LOS_NONE: default: // don't draw anything break; } } // Draw the items that are in LOS if (tile->flags & MAPTILE_OUT_OF_SIGHT) { continue; } CA_FOREACH(ThingId, tid, tile->things) const TTileItem *ti = ThingIdGetTileItem(tid); // Drawn later if (TileItemDrawLast(ti)) { continue; } CArrayPushBack(&b->displaylist, &ti); CA_FOREACH_END() } DrawBufferSortDisplayList(b); CA_FOREACH(const TTileItem *, tp, b->displaylist) DrawThing(b, *tp, offset); CA_FOREACH_END() tile += X_TILES - b->Size.x; } }