Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Neue Implementation der Draig-Feuerwand #1112

Merged
merged 14 commits into from
Feb 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# 30.0

- Feuerwand erzeugt curses in den beiden Regionen.
- Feuerwand-Auflösung nicht mehr über aging borders implementiert.
- age_borders Mechanismus ist damit überflüssig.
- Dateiformat: Kein Magier mehr in wall_data
- Fluch brechen, Antimagiekristal und Zerstoere Magie können Feuerwand auflösen
- Fluch brechen benutzt jetzt den selben Code wie andere Antimagie

# 29.4

- Weg der Bäume kostet auch bei resistenten Zielen [Bug 3051]
Expand Down
6 changes: 6 additions & 0 deletions res/core/messages.xml
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,12 @@
<arg name="id" type="int"/>
</type>
</message>
<message name="curseinfo::firewall" section="events">
<type>
<arg name="direction" type="direction"/>
<arg name="id" type="int"/>
</type>
</message>
<message name="curseinfo::speed_1" section="events">
<type>
<arg name="number" type="int"/>
Expand Down
4 changes: 4 additions & 0 deletions res/translations/messages.de.po
Original file line number Diff line number Diff line change
Expand Up @@ -2217,6 +2217,10 @@ msgctxt "curseinfo"
msgid "slave_1"
msgstr "\"$unit($unit) wird noch $int($duration) $if($eq($duration,1), \"Woche\", \"Wochen\") unter unserem Bann stehen. ($int36($id))\""

msgctxt "curseinfo"
msgid "firewall"
msgstr "\"Eine magische Feuerwand blockiert den Weg nach $direction($direction). ($int36($id))\""

msgid "alliance::lost"
msgstr "\"$alliance($alliance) scheidet aus dem Spiel aus, nachdem alle Tempel verloren gingen.\""

Expand Down
4 changes: 4 additions & 0 deletions res/translations/messages.en.po
Original file line number Diff line number Diff line change
Expand Up @@ -2217,6 +2217,10 @@ msgctxt "curseinfo"
msgid "slave_1"
msgstr "\"$unit($unit) will be under our influence for $int($duration) more $if($eq($duration,1), \"week\", \"weeks\"). ($int36($id))\""

msgctxt "curseinfo"
msgid "firewall"
msgstr "\"A wall of magical fire is blocking the way $direction($direction). ($int36($id))\""

msgid "alliance::lost"
msgstr "\"$alliance($alliance) has to leave the game after all their temples were lost.\""

Expand Down
28 changes: 28 additions & 0 deletions scripts/tests/e2/spells.lua
Original file line number Diff line number Diff line change
Expand Up @@ -502,3 +502,31 @@ function test_charming()

assert_equal(f2, u2.faction)
end

function test_firewall()
local r1 = region.create(0, 0, 'plain')
local r2 = region.create(1, 0, 'plain')
local f = faction.create('human')
local u = unit.create(f, r1, 1)
local u2 = unit.create(f, r1, 1)
local uno = u.id

assert_true(u2.hp == u2.hp_max)
u.magic = 'draig'
u:set_skill('magic', 24)
u.aura = 1000
u:add_spell('firewall')

u:add_order("ZAUBERE STUFE 1 'Feuerwand' OST")
u2:set_orders("NACH OST") -- no effect yet in same week
process_orders()
assert_true(u2.hp == u2.hp_max)
u:clear_orders()
u2:set_orders("NACH WEST") -- should take damage now
assert_true(r1:has_border("firewall", directions.EAST))
assert_true(r2:has_border("firewall", directions.WEST))
process_orders()
assert_false(r1:has_border("firewall", directions.EAST))
assert_false(r2:has_border("firewall", directions.WEST))
assert_true(u2.hp < u2.hp_max)
end
2 changes: 1 addition & 1 deletion src/battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ union variant;
#define FL_HEALING_USED 128 /* has used a healing potion */

typedef struct bfaction {
struct bfaction* next;
struct bfaction* next; /* TODO: stb_ds benutzen? */
struct faction* faction;
bool attacker;
} bfaction;
Expand Down
24 changes: 24 additions & 0 deletions src/bind_region.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <kernel/calendar.h>
#include <kernel/curse.h>
#include <kernel/region.h>
#include "kernel/connection.h"
#include "kernel/direction.h"
#include <kernel/resources.h>
#include <kernel/unit.h>
Expand Down Expand Up @@ -263,6 +264,28 @@ static int tolua_region_get_roads(lua_State * L)
return 1;
}

static int tolua_region_has_border(lua_State *L)
{
region *r = (region *)tolua_tousertype(L, 1, NULL);
const char * bname = tolua_tostring(L, 2, NULL);
const border_type *btype = bname ? find_bordertype(bname) : NULL;

if (btype) {
direction_t dir = (direction_t)tolua_tonumber(L, 3, 0);
region *r2 = rconnect(r, dir);
connection *b;
for (b = get_borders(r, r2); b; b = b->next) {
if (b->type == btype) {
lua_pushboolean(L, true);
return 1;
}
}
lua_pushboolean(L, false);
return 1;
}
return 0;
}

static int tolua_region_get_luxury(lua_State * L)
{
region *r = (region *)tolua_tousertype(L, 1, NULL);
Expand Down Expand Up @@ -829,6 +852,7 @@ void tolua_region_open(lua_State * L)
tolua_function(L, "next", tolua_region_get_next);
tolua_variable(L, "adj", tolua_region_get_adj, NULL);
tolua_variable(L, "roads", tolua_region_get_roads, NULL);
tolua_function(L, "has_border", tolua_region_has_border);

tolua_variable(L, "luxury", &tolua_region_get_luxury,
&tolua_region_set_luxury);
Expand Down
2 changes: 1 addition & 1 deletion src/helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ static void push_param(lua_State * L, char c, spellparameter* param)
else if (c == 'r')
tolua_pushusertype(L, param->data.sh, "region");
else if (c == 'c')
tolua_pushstring(L, param->data.s);
tolua_pushstring(L, param->data.xs);
else {
log_error("unsupported syntax %c.\n", c);
lua_pushnil(L);
Expand Down
10 changes: 7 additions & 3 deletions src/items.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,12 @@ struct order *ord)
/* Kann auch von Nichtmagiern benutzt werden, erzeugt eine
* Antimagiezone, die zwei Runden bestehen bleibt */
static int
use_antimagiccrystal(unit * u, const struct item_type *itype, int amount,
struct order *ord)
use_antimagiccrystal(
unit * u,
const struct item_type *itype,
int amount,
struct order *ord
)
{
region *r = u->region;
const resource_type *rt_crystal;
Expand Down Expand Up @@ -166,7 +170,7 @@ struct order *ord)
continue;
}

force = destr_curse(c, effect, force);
force = reduce_curse(c, effect, force, r);
if (c->vigour <= 0) {
a_remove(&r->attribs, a);
}
Expand Down
37 changes: 10 additions & 27 deletions src/kernel/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "terrain.h"
#include "unit.h"

#include <spells/borders.h>
#include <kernel/attrib.h>
#include <kernel/gamedata.h>

Expand Down Expand Up @@ -132,6 +133,7 @@ connection *create_border(border_type * type, region * from, region * to)

void erase_border(connection * b)
{
assert(b);
if (b->from && b->to) {
connection **bp = get_borders_i(b->from, b->to);
assert(*bp != NULL || !"error: connection is not registered");
Expand Down Expand Up @@ -304,33 +306,6 @@ attrib_type at_countdown = {
a_readint
};

void age_borders(void)
{
connection **deleted = NULL;
int i;

for (i = 0; i != BORDER_MAXHASH; ++i) {
connection *bhash = borders[i];
for (; bhash; bhash = bhash->nexthash) {
connection *b = bhash;
for (; b; b = b->next) {
if (b->type->age) {
if (b->type->age(b) == AT_AGE_REMOVE) {
arrput(deleted, b);
}
}
}
}
}
if (deleted) {
size_t qi, ql;
for (ql = arrlen(deleted), qi = 0; qi != ql; ++qi) {
erase_border(deleted[qi]);
}
arrfree(deleted);
}
}

/********
* implementation of a couple of borders. this shouldn't really be in here, so
* let's keep it separate from the more general stuff above
Expand Down Expand Up @@ -513,6 +488,14 @@ int read_borders(gamedata *data)
if (type->read) {
connection *b = NULL;

if (data->version < WALL_DATA_VERSION) {
/* remove legacy firewalls */
if (type == &bt_firewall) {
log_info("removing legacy firewall in %s", regionname(from, NULL));
b = &dummy;
b->data.v = NULL;
}
}
if (data->version < FIX_SEAROADS_VERSION) {
/* bug 2694: eliminate roads in oceans */
if (type->terrain_flags != 0 && type->terrain_flags != fval(from->terrain, type->terrain_flags)) {
Expand Down
3 changes: 0 additions & 3 deletions src/kernel/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,6 @@ extern "C" {
struct region *(*move) (const connection *, struct unit * u,
struct region * from, struct region * to, bool routing);
/* executed when the units traverses this connection */
int(*age) (struct connection *);
/* return 0 if connection needs to be removed. >0 if still aging, <0 if not aging */
struct border_type *next; /* for internal use only */
} border_type;

Expand All @@ -94,7 +92,6 @@ extern "C" {

int read_borders(struct gamedata *store);
void write_borders(struct storage *store);
void age_borders(void);

/* provide default implementations for some member functions: */
void b_read(connection * b, struct gamedata *store);
Expand Down
14 changes: 7 additions & 7 deletions src/kernel/curse.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,14 @@ int curse_age(attrib * a, void *owner)
c_clearflag(c, CURSE_ISNEW);

if ((c_flags(c) & CURSE_NOAGE) == 0) {
if (--c->duration <= 0) {
result = AT_AGE_REMOVE;
}
if (c->type->age) {
if (c->type->age(c) == 0) {
if (c->type->age(c, owner) == 0) {
result = AT_AGE_REMOVE;
}
}
else if (--c->duration <= 0) {
result = AT_AGE_REMOVE;
}
}
return result;
}
Expand Down Expand Up @@ -691,12 +691,12 @@ message *cinfo_simple(const void *obj, objtype_t typ, const struct curse * c,
* die Kraft des Curse um die halbe Staerke der Antimagie reduziert.
* Zurueckgegeben wird der noch unverbrauchte Rest von force.
*/
double destr_curse(curse * c, int cast_level, double force)
double reduce_curse(curse * c, int cast_level, double force, void *curse_target)
{
if (cast_level < c->vigour) { /* Zauber ist nicht stark genug */
force -= c->vigour;
if (c->type->change_vigour) {
c->type->change_vigour(c, -(cast_level + 1) / 2);
c->type->change_vigour(c, -(cast_level + 1) / 2, curse_target);
}
else {
c->vigour -= (cast_level + 1) / 2.0;
Expand All @@ -706,7 +706,7 @@ double destr_curse(curse * c, int cast_level, double force)
if (force >= c->vigour) { /* reicht die Kraft noch aus? */
force -= c->vigour;
if (c->type->change_vigour) {
c->type->change_vigour(c, -c->vigour);
c->type->change_vigour(c, -c->vigour, curse_target);
}
else {
c->vigour = 0;
Expand Down
6 changes: 3 additions & 3 deletions src/kernel/curse.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,13 @@ extern "C" {
int mergeflags;
struct message *(*curseinfo) (const void *, objtype_t,
const struct curse *, int);
void(*change_vigour) (struct curse *, double);
void(*change_vigour) (struct curse *, double, void *);
int(*read) (struct gamedata *data, struct curse *, void *target);
int(*write) (struct storage *store, const struct curse *,
const void *target);
int(*cansee) (const struct faction *, const void *, objtype_t,
const struct curse *, int);
int(*age) (struct curse *);
int(*age) (struct curse *, void *);
void(*construct) (struct curse *);
void(*destroy) (struct curse *);
} curse_type;
Expand Down Expand Up @@ -231,7 +231,7 @@ extern "C" {

int curse_age(struct attrib *a, void *owner);

double destr_curse(struct curse *c, int cast_level, double force);
double reduce_curse(struct curse *c, int cast_level, double force, void *curse_target);

bool is_cursed_with(const struct attrib *ap, const struct curse *c);

Expand Down
3 changes: 2 additions & 1 deletion src/kernel/gamedata.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@
#define SKILL_DAYS_VERSION 381 /* skills are stored as days, not weeks */
#define BORDER_ID_VERSION 382 /* borders no longer have an id, from turn 1376 */
#define SLAVE_DATA_VERSION 383 /* ct_slavery has curse-data */
#define WALL_DATA_VERSION 384 /* wall_data no longer has mage stored in it */

#define RELEASE_VERSION SLAVE_DATA_VERSION /* use for new datafiles */
#define RELEASE_VERSION WALL_DATA_VERSION /* use for new datafiles */
#define MIN_VERSION UIDHASH_VERSION /* minimal datafile we support */
#define MAX_VERSION RELEASE_VERSION /* change this if we can need to read the future datafile, and we can do so */

Expand Down
41 changes: 40 additions & 1 deletion src/kernel/order.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ static int create_data(keyword_t kwd, const char *s,
if (kwd == K_STUDY || kwd == K_AUTOSTUDY || kwd == K_FORGET) {
const char * sptr = s;
skill_t sk = findskill(parse_token_depr(&sptr), lang);
if (sk != SK_MAGIC && sk != NOSKILL) {
if (kwd == K_FORGET || (sk != SK_MAGIC && sk != NOSKILL)) {
return ((int)sk)-100;
}
}
Expand Down Expand Up @@ -652,3 +652,42 @@ order *default_order(const struct locale *lang)
return NULL;
}

bool translate_order(order *ord, const struct locale *from_lang, const struct locale *to_lang)
{
(void)to_lang;
(void)from_lang;

if (ord->id <= 0) {
/* no arguments, no translation needed */
return true;
}
switch (getkeyword(ord)) {
case NOKEYWORD:
case K_ATTACK:
case K_BANNER:
case K_DRIVE:
case K_FOLLOW:
case K_GROUP:
case K_KOMMENTAR:
case K_MAIL:
case K_NUMBER:
case K_PASSWORD:
case K_PREFIX:
case K_RECRUIT:
case K_SPY:
case K_STEAL:
case K_TEACH:
case K_TRANSPORT:
case K_URSPRUNG:
/* we can keep these, they do not use translated strings */
return true;
case K_FORGET:
case K_AUTOSTUDY:
case K_STUDY:
/* we can keep these, they do not use translated strings */
return (ord->id < 0);
default:
return false;
}
}

Loading