engine-c: scrap mounds + lingering FX + secondary SE clash
This commit is contained in:
parent
0897293f51
commit
4411169cc3
5 changed files with 243 additions and 22 deletions
|
|
@ -357,8 +357,82 @@ static void place_showcase(Game *g, Faction human, Faction enemy) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* scrap mound fields: SE of HQ + corridor toward primary clash */
|
||||
{
|
||||
int hx_t = sx, hy_t = sy;
|
||||
for (int dy = -2; dy <= 8; dy++) {
|
||||
for (int dx = -2; dx <= 10; dx++) {
|
||||
int tx = hx_t + dx, ty = hy_t + dy;
|
||||
if (!map_in_bounds(&g->map, tx, ty)) continue;
|
||||
Tile *t = map_tile(&g->map, tx, ty);
|
||||
if (!t || t->occupied || !t->walkable) continue;
|
||||
if (t->terrain == T_ROAD) continue;
|
||||
int h = (dx * 11 + dy * 9) & 7;
|
||||
if (h == 0 || h == 3) {
|
||||
t->terrain = T_SCRAP;
|
||||
t->scrap = (uint8_t)(110 + ((dx * 17 + dy * 13) & 127));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* secondary clash front SE of HQ (second fight plate in crop) */
|
||||
float rx2 = wx + 40.0f, ry2 = wy + 70.0f;
|
||||
{
|
||||
int ctx2, cty2;
|
||||
map_world_to_tile(rx2, ry2, &ctx2, &cty2);
|
||||
for (int dy = -5; dy <= 5; dy++) {
|
||||
for (int dx = -6; dx <= 6; dx++) {
|
||||
int tx = ctx2 + dx, ty = cty2 + dy;
|
||||
if (!map_in_bounds(&g->map, tx, ty)) continue;
|
||||
Tile *t = map_tile(&g->map, tx, ty);
|
||||
if (!t || !t->walkable) continue;
|
||||
int d2 = dx * dx + dy * dy;
|
||||
if (d2 <= 2) {
|
||||
t->terrain = T_ROAD;
|
||||
t->scrap = 0;
|
||||
} else if (d2 <= 10) {
|
||||
t->terrain = T_RUBBLE;
|
||||
t->scrap = 0;
|
||||
} else if (d2 <= 24 && ((dx + dy * 2) & 3) == 0) {
|
||||
t->terrain = T_SCRAP;
|
||||
t->scrap = (uint8_t)(100 + ((dx * 19 + dy * 11) & 127));
|
||||
}
|
||||
}
|
||||
}
|
||||
/* short approach from HQ south gate toward secondary */
|
||||
{
|
||||
int steps = abs(ctx2 - sx) + abs(cty2 - sy);
|
||||
if (steps < 1) steps = 1;
|
||||
for (int s = 0; s <= steps; s++) {
|
||||
int tx = sx + (ctx2 - sx) * s / steps;
|
||||
int ty = sy + (cty2 - sy) * s / steps;
|
||||
if (!map_in_bounds(&g->map, tx, ty)) continue;
|
||||
Tile *t = map_tile(&g->map, tx, ty);
|
||||
if (!t || !t->walkable) continue;
|
||||
if (t->occupied) continue;
|
||||
t->terrain = T_ROAD;
|
||||
t->scrap = 0;
|
||||
}
|
||||
}
|
||||
bld_spawn(g, BT_TURRET, human, ctx2 - 2, cty2);
|
||||
bld_spawn(g, BT_TURRET, human, ctx2 + 1, cty2 + 1);
|
||||
bld_spawn(g, BT_WALL, human, ctx2 - 3, cty2);
|
||||
bld_spawn(g, BT_WALL, human, ctx2 - 3, cty2 + 1);
|
||||
bld_force_complete(g);
|
||||
}
|
||||
/* Survivor SE defenders */
|
||||
unit_spawn(g, UT_TANK, human, rx2 - 18, ry2 - 8);
|
||||
unit_spawn(g, UT_TANK, human, rx2 - 6, ry2 + 10);
|
||||
unit_spawn(g, UT_JEEP, human, rx2 - 28, ry2 + 4);
|
||||
unit_spawn(g, UT_FLAME, human, rx2 - 22, ry2 + 18);
|
||||
unit_spawn(g, UT_BUGGY, human, rx2 - 34, ry2 - 12);
|
||||
for (int i = 0; i < 5; i++)
|
||||
unit_spawn(g, UT_INFANTRY, human,
|
||||
rx2 - 12 + (i % 3) * 12, ry2 - 16 + (i / 3) * 14);
|
||||
|
||||
int raid[56];
|
||||
int rn = 0;
|
||||
for (int i = 0; i < 8; i++)
|
||||
|
|
@ -389,6 +463,24 @@ static void place_showcase(Game *g, Faction human, Faction enemy) {
|
|||
raid[rn++] = unit_spawn(g, UT_INFANTRY, enemy,
|
||||
rx - 28 + (i % 4) * 14, ry - 8 + (i / 4) * 14);
|
||||
|
||||
/* secondary Evolved pack at SE clash (room left in raid[56]) */
|
||||
int rn_pri = rn;
|
||||
for (int i = 0; i < 4; i++)
|
||||
raid[rn++] = unit_spawn(g, UT_MUTANT, enemy,
|
||||
rx2 + 10 + (i % 2) * 16, ry2 + 8 + (i / 2) * 14);
|
||||
for (int i = 0; i < 2; i++)
|
||||
raid[rn++] = unit_spawn(g, UT_BEAST, enemy, rx2 + 28 + i * 14, ry2 + 4 + i * 10);
|
||||
raid[rn++] = unit_spawn(g, UT_BUGGY, enemy, rx2 + 18, ry2 - 10);
|
||||
raid[rn++] = unit_spawn(g, UT_BUGGY, enemy, rx2 + 34, ry2 + 16);
|
||||
raid[rn++] = unit_spawn(g, UT_JEEP, enemy, rx2 + 42, ry2 + 2);
|
||||
raid[rn++] = unit_spawn(g, UT_TANK, enemy, rx2 + 50, ry2 + 12);
|
||||
raid[rn++] = unit_spawn(g, UT_TANK, enemy, rx2 + 58, ry2 - 6);
|
||||
raid[rn++] = unit_spawn(g, UT_RAVAGER, enemy, rx2 + 46, ry2 + 22);
|
||||
raid[rn++] = unit_spawn(g, UT_FLAME, enemy, rx2 + 22, ry2 + 26);
|
||||
raid[rn++] = unit_spawn(g, UT_MISSILE, enemy, rx2 + 64, ry2 + 8);
|
||||
for (int i = 0; i < 2; i++)
|
||||
raid[rn++] = unit_spawn(g, UT_INFANTRY, enemy,
|
||||
rx2 + 6 + i * 12, ry2 + 20 + i * 6);
|
||||
|
||||
/* seed Survivor harvester beds so cargo silhouette is visible in shot */
|
||||
{
|
||||
|
|
@ -404,66 +496,104 @@ static void place_showcase(Game *g, Faction human, Faction enemy) {
|
|||
}
|
||||
}
|
||||
|
||||
/* pre-damage for HP-bar variety (sim may add more) */
|
||||
/* pre-damage for HP-bar variety at both clash loci */
|
||||
for (int i = 0; i < g->unit_count; i++) {
|
||||
Unit *u = &g->units[i];
|
||||
if (u->dead || u->max_hp <= 0) continue;
|
||||
float dx = u->x - rx, dy = u->y - ry;
|
||||
if (dx * dx + dy * dy > 140.0f * 140.0f) continue;
|
||||
float dx2 = u->x - rx2, dy2 = u->y - ry2;
|
||||
int near = (dx * dx + dy * dy <= 140.0f * 140.0f)
|
||||
|| (dx2 * dx2 + dy2 * dy2 <= 110.0f * 110.0f);
|
||||
if (!near) continue;
|
||||
float f = 0.35f + 0.45f * ((i * 17) % 100) / 100.0f;
|
||||
u->hp = u->max_hp * f;
|
||||
}
|
||||
|
||||
/* FX seeds at the clash locus */
|
||||
/* FX seeds at primary + secondary clash loci */
|
||||
particle_burst(g, rx, ry, 28, 1, 255, 140, 40);
|
||||
particle_burst(g, rx + 20, ry - 10, 18, 0, 90, 90, 90);
|
||||
particle_burst(g, rx - 15, ry + 12, 22, 2, 255, 220, 80);
|
||||
particle_burst(g, rx + 40, ry + 5, 14, 1, 255, 100, 30);
|
||||
particle_burst(g, rx + 10, ry - 25, 16, 3, 80, 70, 60);
|
||||
particle_burst(g, rx2, ry2, 24, 1, 255, 130, 35);
|
||||
particle_burst(g, rx2 + 16, ry2 - 8, 16, 0, 100, 95, 85);
|
||||
particle_burst(g, rx2 - 12, ry2 + 10, 18, 2, 255, 210, 70);
|
||||
particle_burst(g, rx2 + 28, ry2 + 6, 12, 1, 255, 90, 25);
|
||||
particle_burst(g, rx2 + 8, ry2 + 20, 14, 3, 85, 75, 55);
|
||||
|
||||
/* point raid at nearest human combat units / HQ */
|
||||
/* point primary raid at nearest human combat / HQ; secondary at SE prey */
|
||||
int hq = -1;
|
||||
for (int i = 0; i < g->bld_count; i++)
|
||||
if (!g->buildings[i].dead && g->buildings[i].faction == human
|
||||
&& g->buildings[i].type == BT_BASE) { hq = i; break; }
|
||||
int prey = -1;
|
||||
int prey = -1, prey2 = -1;
|
||||
float prey_d2 = 1e12f, prey2_d2 = 1e12f;
|
||||
for (int i = 0; i < g->unit_count; i++) {
|
||||
Unit *u = &g->units[i];
|
||||
if (u->dead || u->faction != human) continue;
|
||||
if (u->type == UT_HARVESTER || u->type == UT_MEDIC) continue;
|
||||
prey = i; break;
|
||||
float d1 = (u->x - rx) * (u->x - rx) + (u->y - ry) * (u->y - ry);
|
||||
float d2 = (u->x - rx2) * (u->x - rx2) + (u->y - ry2) * (u->y - ry2);
|
||||
if (d1 < prey_d2) { prey_d2 = d1; prey = i; }
|
||||
if (d2 < prey2_d2) { prey2_d2 = d2; prey2 = i; }
|
||||
}
|
||||
int tur2 = -1;
|
||||
for (int i = 0; i < g->bld_count; i++) {
|
||||
Building *b = &g->buildings[i];
|
||||
if (b->dead || b->faction != human || b->type != BT_TURRET) continue;
|
||||
float bx = (float)(b->tx * TILE + b->w * TILE / 2);
|
||||
float by = (float)(b->ty * TILE + b->h * TILE / 2);
|
||||
float d2 = (bx - rx2) * (bx - rx2) + (by - ry2) * (by - ry2);
|
||||
if (d2 < 90.0f * 90.0f) { tur2 = i; break; }
|
||||
}
|
||||
for (int i = 0; i < rn; i++) {
|
||||
if (raid[i] < 0) continue;
|
||||
if (prey >= 0) unit_issue_attack_unit(g, raid[i], prey);
|
||||
else if (hq >= 0) unit_issue_attack_bld(g, raid[i], hq);
|
||||
if (i < rn_pri) {
|
||||
if (prey >= 0) unit_issue_attack_unit(g, raid[i], prey);
|
||||
else if (hq >= 0) unit_issue_attack_bld(g, raid[i], hq);
|
||||
} else {
|
||||
if (prey2 >= 0) unit_issue_attack_unit(g, raid[i], prey2);
|
||||
else if (tur2 >= 0) unit_issue_attack_bld(g, raid[i], tur2);
|
||||
else if (hq >= 0) unit_issue_attack_bld(g, raid[i], hq);
|
||||
}
|
||||
}
|
||||
|
||||
/* human combat units engage nearest raiders (spread targets) */
|
||||
/* human combat units engage nearest raiders (both fronts) */
|
||||
int ridx = 0;
|
||||
for (int i = 0; i < g->unit_count; i++) {
|
||||
Unit *u = &g->units[i];
|
||||
if (u->dead || u->faction != human) continue;
|
||||
if (u->type == UT_HARVESTER || u->type == UT_MEDIC) continue;
|
||||
float dx = u->x - rx, dy = u->y - ry;
|
||||
if (dx * dx + dy * dy > 220.0f * 220.0f) continue;
|
||||
float dx2 = u->x - rx2, dy2 = u->y - ry2;
|
||||
int near = (dx * dx + dy * dy <= 220.0f * 220.0f)
|
||||
|| (dx2 * dx2 + dy2 * dy2 <= 160.0f * 160.0f);
|
||||
if (!near) continue;
|
||||
int prefer_sec = (dx2 * dx2 + dy2 * dy2) < (dx * dx + dy * dy);
|
||||
int lo = prefer_sec ? rn_pri : 0;
|
||||
int hi = prefer_sec ? rn : rn_pri;
|
||||
if (hi <= lo) { lo = 0; hi = rn; }
|
||||
int tgt = -1;
|
||||
for (int k = 0; k < rn; k++) {
|
||||
int ri = raid[(ridx + k) % rn];
|
||||
int span = hi - lo;
|
||||
for (int k = 0; k < span; k++) {
|
||||
int ri = raid[lo + (ridx + k) % span];
|
||||
if (ri >= 0 && !g->units[ri].dead) { tgt = ri; ridx += k + 1; break; }
|
||||
}
|
||||
if (tgt >= 0) unit_issue_attack_unit(g, i, tgt);
|
||||
}
|
||||
|
||||
/* select a front-line squad for yellow selection boxes in the shot */
|
||||
/* select front-line squads on both clashes for yellow selection boxes */
|
||||
unit_clear_selection(g);
|
||||
int nsel = 0;
|
||||
for (int i = 0; i < g->unit_count && nsel < 8; i++) {
|
||||
for (int i = 0; i < g->unit_count && nsel < 10; i++) {
|
||||
Unit *u = &g->units[i];
|
||||
if (u->dead || u->faction != human) continue;
|
||||
if (u->type == UT_HARVESTER || u->type == UT_MEDIC) continue;
|
||||
float dx = u->x - rx, dy = u->y - ry;
|
||||
if (dx * dx + dy * dy > 120.0f * 120.0f) continue;
|
||||
float dx2 = u->x - rx2, dy2 = u->y - ry2;
|
||||
int near = (dx * dx + dy * dy <= 120.0f * 120.0f)
|
||||
|| (dx2 * dx2 + dy2 * dy2 <= 90.0f * 90.0f);
|
||||
if (!near) continue;
|
||||
unit_select_single(g, i, 1);
|
||||
nsel++;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue