static void SaveTemplateDisplayTitle( const menu_t *menu, GraphicsDevice *g, const Vec2i pos, const Vec2i size, const void *data) { UNUSED(g); const PlayerSelectMenuData *d = data; char buf[256]; UNUSED(menu); UNUSED(size); // Display "Save <template>..." title const PlayerData *p = PlayerDataGetByUID(d->display.PlayerUID); sprintf(buf, "Save %s...", p->name); FontStr(buf, Vec2iAdd(pos, Vec2iNew(0, 0))); }
void MapGenerateRandomExitArea(Map *map) { const Tile *t = NULL; for (int i = 0; i < 10000 && (t == NULL ||!TileCanWalk(t)); i++) { map->ExitStart.x = (rand() % (abs(map->Size.x) - EXIT_WIDTH - 1)); map->ExitEnd.x = map->ExitStart.x + EXIT_WIDTH + 1; map->ExitStart.y = (rand() % (abs(map->Size.y) - EXIT_HEIGHT - 1)); map->ExitEnd.y = map->ExitStart.y + EXIT_HEIGHT + 1; // Check that the exit area is walkable const Vec2i center = Vec2iNew( (map->ExitStart.x + map->ExitEnd.x) / 2, (map->ExitStart.y + map->ExitEnd.y) / 2); t = MapGetTile(map, center); } }
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); } } } }
void MapMakeRoom(Map *map, int xOrigin, int yOrigin, int width, int height) { int x, y; // Set the perimeter walls and interior // If the tile is a room interior already, do not turn it into a wall // This is due to overlapping rooms for (y = yOrigin; y < yOrigin + height; y++) { for (x = xOrigin; x < xOrigin + width; x++) { if (y == yOrigin || y == yOrigin + height - 1 || x == xOrigin || x == xOrigin + width - 1) { if (IMapGet(map, Vec2iNew(x, y)) == MAP_FLOOR) { IMapSet(map, Vec2iNew(x, y), MAP_WALL); } } else { IMapSet(map, Vec2iNew(x, y), MAP_ROOM); } } } // Check perimeter again; if there are walls where both sides contain // rooms, remove the wall as the rooms have merged for (y = yOrigin; y < yOrigin + height; y++) { for (x = xOrigin; x < xOrigin + width; x++) { if (y == yOrigin || y == yOrigin + height - 1 || x == xOrigin || x == xOrigin + width - 1) { if (((IMapGet(map, Vec2iNew(x + 1, y)) & MAP_MASKACCESS) == MAP_ROOM && (IMapGet(map, Vec2iNew(x - 1, y)) & MAP_MASKACCESS) == MAP_ROOM) || ((IMapGet(map, Vec2iNew(x, y + 1)) & MAP_MASKACCESS) == MAP_ROOM && (IMapGet(map, Vec2iNew(x, y - 1)) & MAP_MASKACCESS) == MAP_ROOM)) { IMapSet(map, Vec2iNew(x, y), MAP_ROOM); } } } } }
static void DrawAmmoUpdate(const HUDNumPopup *u, const int flags) { if (u->Amount == 0) { return; } const PlayerData *p = PlayerDataGetByUID(u->u.PlayerUID); if (!IsPlayerAlive(p)) return; const int rowHeight = 1 + FontH(); const int y = 5 + rowHeight * 4 + LIVES_ROW_EXTRA_Y; const TActor *a = ActorGetByUID(p->ActorUID); const Weapon *w = ActorGetGun(a); char gunNameBuf[256]; sprintf(gunNameBuf, "%s %%d", w->Gun->name); const int ammo = ActorGunGetAmmo(a, w); DrawNumUpdate(u, gunNameBuf, ammo, Vec2iNew(5 + GUN_ICON_PAD, y), flags); }
static void SetupSpawner( MapObject *m, const char *spawnerName, const char *pickupClassName) { memset(m, 0, sizeof *m); CSTRDUP(m->Name, spawnerName); m->Pic.Type = PICTYPE_NORMAL; m->Pic.u.Pic = PicManagerGetPic(&gPicManager, "spawn_pad"); m->Pic.UseMask = true; m->Pic.u1.Mask = colorWhite; const Vec2i size = CPicGetSize(&m->Pic); m->Offset = Vec2iNew(-size.x / 2, TILE_HEIGHT / 2 - size.y); m->Size = TILE_SIZE; m->Health = 0; m->DrawLast = true; m->Type = MAP_OBJECT_TYPE_PICKUP_SPAWNER; m->u.PickupClass = StrPickupClass(pickupClassName); }
static bool IsPosOK(TActor *actor, Vec2i pos) { Vec2i realPos = Vec2iFull2Real(pos); Vec2i size = Vec2iNew(actor->tileItem.w, actor->tileItem.h); if (IsCollisionWallOrEdge(&gMap, realPos, size)) { return 0; } if (GetItemOnTileInCollision( &actor->tileItem, realPos, TILEITEM_IMPASSABLE, CalcCollisionTeam(1, actor), gCampaign.Entry.Mode == CAMPAIGN_MODE_DOGFIGHT)) { return 0; } return 1; }
Vec2i GunGetMuzzleOffset(const GunDescription *desc, const direction_e dir) { if (!GunHasMuzzle(desc)) { return Vec2iZero(); } gunpic_e g = desc->pic; CASSERT(g >= 0, "Gun has no pic"); int body = (int)g < 0 ? BODY_UNARMED : BODY_ARMED; Vec2i position = Vec2iNew( cGunHandOffset[body][dir].dx + cGunPics[g][dir][GUNSTATE_FIRING].dx + cMuzzleOffset[g][dir].dx, cGunHandOffset[body][dir].dy + cGunPics[g][dir][GUNSTATE_FIRING].dy + cMuzzleOffset[g][dir].dy + BULLET_Z); return Vec2iReal2Full(position); }
Vec2i PlacePlayer( Map *map, const PlayerData *p, const Vec2i firstPos, const bool pumpEvents) { NetMsgActorAdd aa = NetMsgActorAdd_init_default; aa.Id = ActorsGetFreeIndex(); aa.Health = p->Char.maxHealth; aa.PlayerId = p->playerIndex; if (IsPVP(gCampaign.Entry.Mode)) { // In a PVP mode, always place players apart aa.FullPos = PlaceActor(&gMap); } else if (gMission.missionData->Type == MAPTYPE_STATIC && !Vec2iIsZero(gMission.missionData->u.Static.Start)) { // place players near the start point Vec2i startPoint = Vec2iReal2Full(Vec2iCenterOfTile( gMission.missionData->u.Static.Start)); aa.FullPos = PlaceActorNear(map, startPoint, true); } else if (gConfig.Interface.Splitscreen == SPLITSCREEN_NEVER && !Vec2iIsZero(firstPos)) { // If never split screen, try to place players near the first player aa.FullPos = PlaceActorNear(map, firstPos, true); } else { aa.FullPos = PlaceActor(map); } GameEvent e = GameEventNew(GAME_EVENT_ACTOR_ADD); e.u.ActorAdd = aa; GameEventsEnqueue(&gGameEvents, e); if (pumpEvents) { // Process the events that actually place the players HandleGameEvents(&gGameEvents, NULL, NULL, NULL, &gEventHandlers); } return Vec2iNew(aa.FullPos.x, aa.FullPos.y); }
bool DamageSomething( const Vec2i hitVector, const int power, const int flags, const int player, const int uid, TTileItem *target, const special_damage_e special, const HitSounds *hitSounds, const bool allowFriendlyHitSound) { if (!target) { return 0; } const Vec2i pos = Vec2iNew(target->x, target->y); switch (target->kind) { case KIND_CHARACTER: return DoDamageCharacter( pos, hitVector, power, flags, player, uid, target, special, hitSounds, allowFriendlyHitSound); case KIND_OBJECT: DamageObject(power, flags, player, uid, target); if (gConfig.Sound.Hits && hitSounds != NULL && power > 0) { GameEvent es; es.Type = GAME_EVENT_SOUND_AT; es.u.SoundAt.Sound = hitSounds->Object; es.u.SoundAt.Pos = pos; GameEventsEnqueue(&gGameEvents, es); } break; case KIND_PARTICLE: case KIND_MOBILEOBJECT: break; } return 1; }
void UpdateObjects(const int ticks) { for (int i = 0; i < (int)gObjs.size; i++) { TObject *obj = CArrayGet(&gObjs, i); if (!obj->isInUse) { continue; } switch (obj->Class->Type) { case MAP_OBJECT_TYPE_PICKUP_SPAWNER: if (gCampaign.IsClient) break; // If counter -1, it is inactive i.e. already spawned pickup if (obj->counter == -1) { break; } obj->counter -= ticks; if (obj->counter <= 0) { // Deactivate spawner by setting counter to -1 // Spawner reactivated only when ammo taken obj->counter = -1; GameEvent e = GameEventNew(GAME_EVENT_ADD_PICKUP); e.u.AddPickup.UID = PickupsGetNextUID(); strcpy( e.u.AddPickup.PickupClass, obj->Class->u.PickupClass->Name); e.u.AddPickup.IsRandomSpawned = false; e.u.AddPickup.SpawnerUID = obj->uid; e.u.AddPickup.TileItemFlags = 0; e.u.AddPickup.Pos = Vec2i2Net(Vec2iNew(obj->tileItem.x, obj->tileItem.y)); GameEventsEnqueue(&gGameEvents, e); } break; default: // Do nothing break; } } }
static void DrawChatter( const TTileItem *ti, DrawBuffer *b, const Vec2i offset) { if (!ConfigGetBool(&gConfig, "Graphics.ShowHUD")) { return; } const TActor *a = CArrayGet(&gActors, ti->id); // Draw character text if (strlen(a->Chatter) > 0) { const Vec2i textPos = Vec2iNew( a->tileItem.x - b->xTop + offset.x - FontStrW(a->Chatter) / 2, a->tileItem.y - b->yTop + offset.y - ACTOR_HEIGHT); FontStr(a->Chatter, textPos); } }
static void DrawAIChatter(const DrawBuffer *b, const Vec2i offset) { Vec2i pos; const 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) { 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_OUT_OF_SIGHT)) { // Draw the items that are in LOS for (int i = 0; i < (int)tile->things.size; i++) { const ThingId *tid = CArrayGet(&tile->things, i); if (tid->Kind != KIND_CHARACTER) { continue; } const TActor *a = CArrayGet(&gActors, tid->Id); if (!a->aiContext) { continue; } const char *text = AIStateGetChatterText(a->aiContext->State); Vec2i textPos = Vec2iNew( a->tileItem.x - b->xTop + offset.x - TextGetStringWidth(text) / 2, a->tileItem.y - b->yTop + offset.y - ACTOR_HEIGHT); TextString( &gTextManager, AIStateGetChatterText(a->aiContext->State), b->g, textPos); } } } tile += X_TILES - b->Size.x; } }
void DrawActorPics(const ActorPics *pics, const Vec2i pos) { if (pics->IsDead) { if (pics->IsDying) { DrawDyingBody(&gGraphicsDevice, pics, pos); } } else { // Draw shadow if (!pics->IsTransparent) { DrawShadow(&gGraphicsDevice, pos, Vec2iNew(8, 6)); } for (int i = 0; i < BODY_PART_COUNT; i++) { const Pic *pic = pics->OrderedPics[i]; if (pic == NULL) { continue; } const Vec2i drawPos = Vec2iAdd(pos, pics->OrderedOffsets[i]); if (pics->IsTransparent) { BlitBackground( &gGraphicsDevice, pic, drawPos, pics->Tint, true); } else if (pics->Mask != NULL) { BlitMasked(&gGraphicsDevice, pic, drawPos, *pics->Mask, true); } else { BlitCharMultichannel( &gGraphicsDevice, pic, drawPos, pics->Colors); } } } }
void InsertMission(CampaignOptions *co, Mission *mission, int idx) { Mission defaultMission; if (mission == NULL) { MissionInit(&defaultMission); defaultMission.Size = Vec2iNew(48, 48); // Set some default values for the mission defaultMission.u.Classic.CorridorWidth = 1; defaultMission.u.Classic.Rooms.Min = defaultMission.u.Classic.Rooms.Max = 5; defaultMission.u.Classic.Rooms.WallLength = 1; defaultMission.u.Classic.Rooms.WallPad = 1; defaultMission.u.Classic.Doors.Min = defaultMission.u.Classic.Doors.Max = 1; defaultMission.u.Classic.Pillars.Min = defaultMission.u.Classic.Pillars.Max = 1; mission = &defaultMission; } CArrayInsert(&co->Setting.Missions, idx, mission); }
void MenuDisplayItems(MenuSystem *ms) { int d = ms->current->u.normal.displayItems; if ((d & MENU_DISPLAY_ITEMS_CREDITS) && ms->creditsDisplayer != NULL) { ShowCredits(ms->creditsDisplayer); } if (d & MENU_DISPLAY_ITEMS_AUTHORS) { PicPaletted *logo = PicManagerGetOldPic(&gPicManager, PIC_LOGO); DrawTPic( MS_CENTER_X(*ms, logo->w), ms->pos.y + ms->size.y / 12, logo); DrawTextStringSpecial( "Version: " CDOGS_SDL_VERSION, TEXT_TOP | TEXT_RIGHT, ms->pos, ms->size, Vec2iNew(20, 20)); } }
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 bool TryPlacePickup(HealthPickups *h) { Vec2i size = Vec2iNew(HEALTH_W, HEALTH_H); // Attempt to place one in unexplored area for (int i = 0; i < 100; i++) { const Vec2i v = MapGenerateFreePosition(h->map, size); if (!Vec2iIsZero(v) && !MapGetTile(h->map, Vec2iToTile(v))->isVisited) { MapPlaceHealth(v); return true; } } // Attempt to place one in out-of-sight area for (int i = 0; i < 100; i++) { const Vec2i v = MapGenerateFreePosition(h->map, size); const Vec2i fullpos = Vec2iReal2Full(v); const TActor *closestPlayer = AIGetClosestPlayer(fullpos); if (!Vec2iIsZero(v) && (!closestPlayer || CHEBYSHEV_DISTANCE( fullpos.x, fullpos.y, closestPlayer->Pos.x, closestPlayer->Pos.y) >= 256 * 150)) { MapPlaceHealth(v); return true; } } // Attempt to place one anyway for (int i = 0; i < 100; i++) { const Vec2i v = MapGenerateFreePosition(h->map, size); if (!Vec2iIsZero(v)) { MapPlaceHealth(v); return true; } } return false; }
static void DisplayGunIcon( const menu_t *menu, GraphicsDevice *g, const Vec2i pos, const Vec2i size, const void *data) { UNUSED(data); if (menu->u.normal.index >= (int)gMission.Weapons.size) { return; } // Display a gun icon next to the currently selected weapon const GunDescription **gun = CArrayGet(&gMission.Weapons, menu->u.normal.index); const int menuItems = MIN( menu->u.normal.maxItems, (int)menu->u.normal.subMenus.size); const int textScroll = -menuItems * FontH() / 2 + (menu->u.normal.index - menu->u.normal.scroll) * FontH(); const Vec2i iconPos = Vec2iNew( pos.x - (*gun)->Icon->size.x - 4, pos.y + size.y / 2 + textScroll + (FontH() - (*gun)->Icon->size.y) / 2); Blit(g, (*gun)->Icon, iconPos); }
static void MenuDisplayItems(const MenuSystem *ms) { int d = ms->current->u.normal.displayItems; if ((d & MENU_DISPLAY_ITEMS_CREDITS) && ms->creditsDisplayer != NULL) { ShowCredits(ms->creditsDisplayer); } if (d & MENU_DISPLAY_ITEMS_AUTHORS) { PicPaletted *logo = PicManagerGetOldPic(&gPicManager, PIC_LOGO); DrawTPic( MS_CENTER_X(*ms, logo->w), ms->pos.y + ms->size.y / 12, logo); FontOpts opts = FontOptsNew(); opts.HAlign = ALIGN_END; opts.Area = ms->size; opts.Pad = Vec2iNew(20, 20); FontStrOpt("Version: " CDOGS_SDL_VERSION, ms->pos, opts); } }
static bool TryAddMapObject( Mission *m, const MapObject *mo, const Vec2i pos, CArray *objs) { CASSERT(m->Type == MAPTYPE_STATIC, "invalid map type"); const unsigned short tile = MissionGetTile(m, pos); // Remove any items already there TryRemoveMapObjectAt(pos, objs); if (MapObjectIsTileOK( mo, tile, 1, MissionGetTile(m, Vec2iNew(pos.x, pos.y - 1)))) { // Check if the item already has an entry, and add to its list // of positions bool hasAdded = false; for (int i = 0; i < (int)objs->size; i++) { MapObjectPositions *mop = CArrayGet(objs, i); if (mop->M == mo) { CArrayPushBack(&mop->Positions, &pos); hasAdded = true; break; } } // If not, create a new entry if (!hasAdded) { MapObjectPositions mop; mop.M = mo; CArrayInit(&mop.Positions, sizeof(Vec2i)); CArrayPushBack(&mop.Positions, &pos); CArrayPushBack(objs, &mop); } return true; } return false; }
static void DogfightScoresDraw(void *data) { UNUSED(data); // This will only draw once const int w = gGraphicsDevice.cachedConfig.Res.x; const int h = gGraphicsDevice.cachedConfig.Res.y; GraphicsBlitBkg(&gGraphicsDevice); CASSERT( gPlayerDatas.size >= 2 && gPlayerDatas.size <= 4, "Unimplemented number of players for dogfight"); for (int i = 0; i < (int)gPlayerDatas.size; i++) { const Vec2i pos = Vec2iNew( w / 4 + (i & 1) * w / 2, gPlayerDatas.size == 2 ? h / 2 : h / 4 + (i / 2) * h / 2); const PlayerData *p = CArrayGet(&gPlayerDatas, i); DisplayCharacterAndName(pos, &p->Char, p->name); ShowPlayerScore(pos, p->RoundsWon); } }
void MenuDisplayPlayer( menu_t *menu, GraphicsDevice *g, Vec2i pos, Vec2i size, void *data) { UNUSED(g); MenuDisplayPlayerData *d = data; Vec2i playerPos; char s[22]; UNUSED(menu); pos.x -= size.x; // move to left half of screen playerPos = Vec2iNew( pos.x + size.x * 3 / 4 - 12 / 2, CENTER_Y(pos, size, 0)); if (d->currentMenu && strcmp((*d->currentMenu)->name, "Name") == 0) { sprintf(s, "%c%s%c", '\020', d->pData->name, '\021'); } else { strcpy(s, d->pData->name); } DisplayCharacterAndName(playerPos, d->c, s); }
static void AddGraphicsMode(GraphicsDevice *device, const int w, const int h) { // Don't add if mode already exists if (FindValidMode(device, w, h) != -1) { return; } const int size = w * h; int i; for (i = 0; i < (int)device->validModes.size; i++) { // Ordered by actual resolution ascending and scale descending const Vec2i *mode = CArrayGet(&device->validModes, i); const int actualResolution = mode->x * mode->y; if (actualResolution >= size) { break; } } Vec2i mode = Vec2iNew(w, h); CArrayInsert(&device->validModes, i, &mode); }
static UIObject *CreateAddWreckObjs(Vec2i pos, EditorBrush *brush) { UIObject *o2; UIObject *c = UIObjectCreate(UITYPE_CONTEXT_MENU, 0, pos, Vec2iZero()); UIObject *o = UIObjectCreate( UITYPE_CUSTOM, 0, Vec2iZero(), Vec2iNew(TILE_WIDTH + 4, TILE_HEIGHT + 4)); o->ChangeFunc = BrushSetBrushTypeAddWreck; o->u.CustomDrawFunc = DrawWreck; o->OnFocusFunc = ActivateIndexedEditorBrush; o->OnUnfocusFunc = DeactivateIndexedEditorBrush; pos = Vec2iZero(); const int width = 8; for (int i = 0; i < (int)gMapObjects.Destructibles.size; i++) { o2 = UIObjectCopy(o); o2->IsDynamicData = 1; CMALLOC(o2->Data, sizeof(IndexedEditorBrush)); ((IndexedEditorBrush *)o2->Data)->Brush = brush; ((IndexedEditorBrush *)o2->Data)->u.ItemIndex = i; o2->Pos = pos; UIObjectAddChild(c, o2); pos.x += o->Size.x; if (((i + 1) % width) == 0) { pos.x = 0; pos.y += o->Size.y; } const char **name = CArrayGet(&gMapObjects.Destructibles, i); const MapObject *mo = StrMapObject(*name); CSTRDUP(o2->Tooltip, mo->Name); } UIObjectDestroy(o); return c; }
void MenuDisplay(MenuSystem *ms) { menu_t *menu = ms->current; int i; if (menu->type == MENU_TYPE_CUSTOM) { menu->u.customData.displayFunc( ms->graphics, ms->pos, ms->size, menu->u.customData.data); } else { MenuDisplayItems(ms); if (strlen(menu->u.normal.title) != 0) { DrawTextStringSpecial( menu->u.normal.title, TEXT_XCENTER | TEXT_TOP, ms->pos, ms->size, Vec2iNew(0, ms->size.y / 12)); } MenuDisplaySubmenus(ms); } for (i = 0; i < ms->numCustomDisplayFuncs; i++) { ms->customDisplayFuncs[i]( ms->graphics, ms->pos, ms->size, ms->customDisplayDatas[i]); } if (menu->customDisplayFunc) { menu->customDisplayFunc( ms->graphics, ms->pos, ms->size, menu->customDisplayData); } }
// Draw a gauge with an outer background and inner level // +--------------+ // |XXXXXXXX| | // +--------------+ static void DrawGauge( GraphicsDevice *device, Vec2i pos, Vec2i size, int innerWidth, color_t barColor, color_t backColor, const FontAlign hAlign, const FontAlign vAlign) { Vec2i offset = Vec2iUnit(); Vec2i barPos = Vec2iAdd(pos, offset); Vec2i barSize = Vec2iNew(MAX(0, innerWidth - 2), size.y - 2); if (hAlign == ALIGN_END) { int w = device->cachedConfig.Res.x; pos.x = w - pos.x - size.x - offset.x; barPos.x = w - barPos.x - barSize.x - offset.x; } if (vAlign == ALIGN_END) { int h = device->cachedConfig.Res.y; pos.y = h - pos.y - size.y - offset.y; barPos.y = h - barPos.y - barSize.y - offset.y; } DrawRectangle(device, pos, size, backColor, DRAW_FLAG_ROUNDED); DrawRectangle(device, barPos, barSize, barColor, 0); }
static void DrawThing(DrawBuffer *b, const TTileItem *t, const Vec2i offset) { const Vec2i picPos = Vec2iNew( t->x - b->xTop + offset.x, t->y - b->yTop + offset.y); #ifdef DEBUG_DRAW_BOUNDS Draw_Box( picPos.x - t->size.x / 2, picPos.y - t->size.y / 2, picPos.x + t->size.x / 2, picPos.y + t->size.y / 2, colorGray); #endif if (!Vec2iIsZero(t->ShadowSize)) { DrawShadow(&gGraphicsDevice, picPos, t->ShadowSize); } if (t->CPicFunc) { CPicDrawContext c = t->CPicFunc(t->id); CPicDraw(b->g, &t->CPic, picPos, &c); } else if (t->getPicFunc) { Vec2i picOffset; const Pic *pic = t->getPicFunc(t->id, &picOffset); Blit(&gGraphicsDevice, pic, Vec2iAdd(picPos, picOffset)); } else if (t->getActorPicsFunc) { DrawActorPics(t, picPos); } else { (*(t->drawFunc))(picPos, &t->drawData); } }
static Vec2i SeekTowards( const Vec2i pos, const Vec2i vel, const double speedMin, const Vec2i targetPos, const int seekFactor) { // Compensate for bullet's velocity const Vec2i targetVel = Vec2iMinus(Vec2iMinus(targetPos, pos), vel); // Don't seek if the coordinates are too big if (abs(targetVel.x) > 10000 || abs(targetVel.y) > 10000 || Vec2iIsZero(targetVel)) { return vel; } const double targetMag = sqrt( targetVel.x*targetVel.x + targetVel.y*targetVel.y); const double magnitude = MAX(speedMin, Vec2iEqual(vel, Vec2iZero()) ? speedMin : sqrt(vel.x*vel.x + vel.y*vel.y)); const double combinedX = vel.x / magnitude * seekFactor + targetVel.x / targetMag; const double combinedY = vel.y / magnitude * seekFactor + targetVel.y / targetMag; return Vec2iNew( (int)round(combinedX * magnitude / (seekFactor + 1)), (int)round(combinedY * magnitude / (seekFactor + 1))); }
static void AddBrass( const GunDescription *g, const direction_e d, const Vec2i pos) { CASSERT(g->Brass, "Cannot create brass for no-brass weapon"); GameEvent e = GameEventNew(GAME_EVENT_ADD_PARTICLE); e.u.AddParticle.Class = g->Brass; double x, y; const double radians = dir2radians[d]; GetVectorsForRadians(radians, &x, &y); const Vec2i ejectionPortOffset = Vec2iReal2Full(Vec2iScale(Vec2iNew( (int)round(x), (int)round(y)), 7)); const Vec2i muzzleOffset = GunGetMuzzleOffset(g, d); const Vec2i muzzlePosition = Vec2iAdd(pos, muzzleOffset); e.u.AddParticle.FullPos = Vec2iMinus(muzzlePosition, ejectionPortOffset); e.u.AddParticle.Z = g->MuzzleHeight; e.u.AddParticle.Vel = Vec2iScaleDiv( GetFullVectorsForRadians(radians + PI / 2), 3); e.u.AddParticle.Vel.x += (rand() % 128) - 64; e.u.AddParticle.Vel.y += (rand() % 128) - 64; e.u.AddParticle.Angle = RAND_DOUBLE(0, PI * 2); e.u.AddParticle.DZ = (rand() % 6) + 6; e.u.AddParticle.Spin = RAND_DOUBLE(-0.1, 0.1); GameEventsEnqueue(&gGameEvents, e); }