From 090720382102169ac2ef1e80e950afbf2f7a3806 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 14 Feb 2009 09:53:20 +0000 Subject: [PATCH] - merge with revision 4032 of eressea-1.0 - begin to implement morale --- src/combined/Jamfile | 2 +- src/combined/main.c | 5 + src/combined/main.cpp | 1 - src/common/gamecode.vcproj | 1 + src/common/gamecode/creport.c | 2 +- src/common/gamecode/economy.c | 139 +++++++++++++++++---------- src/common/gamecode/laws.c | 2 +- src/common/gamecode/report.c | 2 +- src/common/kernel.vcproj | 1 + src/common/kernel/battle.c | 10 +- src/common/kernel/eressea.c | 4 +- src/common/kernel/eressea.h | 2 +- src/common/kernel/move.c | 2 +- src/common/kernel/region.c | 23 +++-- src/common/kernel/region.h | 16 ++- src/common/spells/spells.c | 31 +++++- src/common/util.vcproj | 1 + src/common/util/dl/malloc.h | 4 +- src/eressea.vcproj | 47 +-------- src/eressea/editor.vcproj | 1 + src/eressea/eressea-lua.vcproj | 3 +- src/eressea/lua/bindings.vcproj | 1 + src/eressea/lua/region.cpp | 4 +- src/eressea/{server.cpp => server.c} | 31 +++--- src/res/eressea2.xml | 3 + src/res/eressea2/terrains.xml | 24 ++--- src/scripts/eressea/multis.lua | 42 +++++++- 27 files changed, 241 insertions(+), 163 deletions(-) create mode 100644 src/combined/main.c delete mode 100644 src/combined/main.cpp rename src/eressea/{server.cpp => server.c} (98%) diff --git a/src/combined/Jamfile b/src/combined/Jamfile index 204669940..c62629839 100644 --- a/src/combined/Jamfile +++ b/src/combined/Jamfile @@ -31,7 +31,7 @@ SERVER_SOURCES = kernel.c stdafx.c util.c - main.cpp + main.c ; if $(MSPACES) { diff --git a/src/combined/main.c b/src/combined/main.c new file mode 100644 index 000000000..544d5faf4 --- /dev/null +++ b/src/combined/main.c @@ -0,0 +1,5 @@ +#include "common/settings.h" +#include "common/config.h" +#include "stdafx.h" + +#include diff --git a/src/combined/main.cpp b/src/combined/main.cpp deleted file mode 100644 index dc8fb0e50..000000000 --- a/src/combined/main.cpp +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/src/common/gamecode.vcproj b/src/common/gamecode.vcproj index 51002c8e4..9c3ad2b70 100644 --- a/src/common/gamecode.vcproj +++ b/src/common/gamecode.vcproj @@ -39,6 +39,7 @@ /> mode!=see_unit) fprintf(F, "\"%s\";visibility\n", visibility[sr->mode]); { - faction * owner = region_owner(r); + faction * owner = get_region_owner(r); if (owner) { fprintf(F, "%d;owner\n", owner->no); } diff --git a/src/common/gamecode/economy.c b/src/common/gamecode/economy.c index 1f4fa4524..ffe63fece 100644 --- a/src/common/gamecode/economy.c +++ b/src/common/gamecode/economy.c @@ -2958,54 +2958,49 @@ entertain_cmd(unit * u, struct order * ord) entertaining += o->qty; } -/* ------------------------------------------------------------- */ - - +/** + * \return number of working spaces taken by players + */ static void -expandwork(region * r, request * work_begin, request * work_end) +expandwork(region * r, request * work_begin, request * work_end, int maxwork) { - int n, earnings; - /* n: verbleibende Einnahmen */ - /* m: maximale Arbeiter */ - int m = maxworkingpeasants(r); - int p_wage = wage(r, NULL, NULL); - int verdienst = 0; - request *o; + int earnings; + /* n: verbleibende Einnahmen */ + /* m: maximale Arbeiter */ + int jobs = maxwork; + int p_wage = wage(r, NULL, NULL); + request *o; - for (o = work_begin; o != work_end; ++o) { - unit * u = o->unit; - int workers; + for (o = work_begin; o != work_end; ++o) { + unit * u = o->unit; + int workers; - if (u->number == 0) continue; + if (u->number == 0) continue; - if (m>=working) workers = u->number; - else { - workers = u->number * m / working; - if (rng_int() % working < (u->number * m) % working) workers++; - } + if (jobs>=working) workers = u->number; + else { + workers = u->number * jobs / working; + if (rng_int() % working < (u->number * jobs) % working) workers++; + } - assert(workers>=0); + assert(workers>=0); - u->n = workers * wage(u->region, u->faction, u->race); + u->n = workers * wage(u->region, u->faction, u->race); - m -= workers; - assert(m>=0); + jobs -= workers; + assert(jobs>=0); - change_money(u, u->n); - working -= o->unit->number; - add_income(u, IC_WORK, o->qty, u->n); + change_money(u, u->n); + working -= o->unit->number; + add_income(u, IC_WORK, o->qty, u->n); fset(u, UFL_LONGACTION|UFL_NOTMOVING); } - n = m * p_wage; - - /* Der Rest wird von den Bauern verdient. n ist das uebriggebliebene - * Geld. */ - - earnings = MIN(n, rpeasants(r) * p_wage) + verdienst; - /* Mehr oder weniger durch Trank "Riesengrass" oder "Faulobstschnaps" */ - - rsetmoney(r, rmoney(r) + earnings); + if (jobs>rpeasants(r)) { + jobs = rpeasants(r); + } + earnings = jobs * p_wage; + rsetmoney(r, rmoney(r) + earnings); } static int @@ -3044,25 +3039,25 @@ do_work(unit * u, order * ord, request * o) static void expandtax(region * r, request * taxorders) { - unit *u; - int i; + unit *u; + int i; - expandorders(r, taxorders); - if (!norders) return; + expandorders(r, taxorders); + if (!norders) return; - for (i = 0; i != norders && rmoney(r) > TAXFRACTION; i++) { - change_money(oa[i].unit, TAXFRACTION); - oa[i].unit->n += TAXFRACTION; - rsetmoney(r, rmoney(r) -TAXFRACTION); - } - free(oa); + for (i = 0; i != norders && rmoney(r) > TAXFRACTION; i++) { + change_money(oa[i].unit, TAXFRACTION); + oa[i].unit->n += TAXFRACTION; + rsetmoney(r, rmoney(r) -TAXFRACTION); + } + free(oa); for (u = r->units; u; u = u->next) { if (u->n >= 0) { add_income(u, IC_TAX, u->wants, u->n); fset(u, UFL_LONGACTION|UFL_NOTMOVING); } - } + } } void @@ -3140,7 +3135,42 @@ auto_work(region * r) } } if (nextworker!=workers) { - expandwork(r, workers, nextworker); + expandwork(r, workers, nextworker, maxworkingpeasants(r)); + } +} + +static void +peasant_taxes(region * r) +{ + faction * f; + unit * u; + building * b; + int money; + int maxsize; + + f = get_region_owner(r); + if (f==NULL) return; + + money = rmoney(r); + if (money<=0) return; + + b = largestbuilding(r, false); + if (b==NULL) return; + + u = buildingowner(r, b); + if (u==NULL || u->faction!=f) return; + + maxsize = buildingeffsize(b, false); + if (maxsize > r->land->morale) { + maxsize = r->land->morale; + } + + if (maxsize>0) { + int taxmoney = (money * maxsize) / 100; + change_money(u, taxmoney); + rsetmoney(r, money - taxmoney); + ADDMSG(&u->faction->msgs, msg_message("income_tax", + "unit region amount", u, r, taxmoney)); } } @@ -3152,7 +3182,8 @@ produce(void) request *taxorders, *sellorders, *stealorders, *buyorders; unit *u; int todo; - int autowork = get_param_int(global.parameters, "work.auto", 0); + int rule_taxation = get_param_int(global.parameters, "rules.economy.taxation", 0); + int rule_autowork = get_param_int(global.parameters, "work.auto", 0); /* das sind alles befehle, die 30 tage brauchen, und die in thisorder * stehen! von allen 30-tage befehlen wird einfach der letzte verwendet @@ -3233,7 +3264,7 @@ produce(void) break; case K_WORK: - if (!autowork && do_work(u, u->thisorder, nextworker)==0) { + if (!rule_autowork && do_work(u, u->thisorder, nextworker)==0) { ++nextworker; } break; @@ -3270,7 +3301,9 @@ produce(void) * letzten Runde berechnen kann, wieviel die Bauern für Unterhaltung * auszugeben bereit sind. */ if (entertaining) expandentertainment(r); - if (!autowork) expandwork(r, workers, nextworker); + if (!rule_autowork) { + expandwork(r, workers, nextworker, maxworkingpeasants(r)); + } if (taxorders) expandtax(r, taxorders); /* An erster Stelle Kaufen (expandbuying), die Bauern so Geld bekommen, um @@ -3294,5 +3327,9 @@ produce(void) assert(rmoney(r) >= 0); assert(rpeasants(r) >= 0); + if (r->land && rule_taxation==1) { + /* new taxation rules, region owners make money based on morale and building */ + peasant_taxes(r); + } } } diff --git a/src/common/gamecode/laws.c b/src/common/gamecode/laws.c index ed63de6a9..5dff299fd 100644 --- a/src/common/gamecode/laws.c +++ b/src/common/gamecode/laws.c @@ -187,7 +187,7 @@ get_food(region *r) { unit *u; int peasantfood = rpeasants(r)*10; - faction * owner = region_owner(r); + faction * owner = get_region_owner(r); /* 1. Versorgung von eigenen Einheiten. Das vorhandene Silber * wird zunächst so auf die Einheiten aufgeteilt, dass idealerweise diff --git a/src/common/gamecode/report.c b/src/common/gamecode/report.c index b70baa499..0c38a30a6 100644 --- a/src/common/gamecode/report.c +++ b/src/common/gamecode/report.c @@ -996,7 +996,7 @@ describe(FILE * F, const seen_region * sr, faction * f) } { - const faction * owner = region_owner(r); + const faction * owner = get_region_owner(r); if (owner!=NULL) { bytes = snprintf(bufp, size, " Die Region ist im Besitz von %s.", factionname(owner)); diff --git a/src/common/kernel.vcproj b/src/common/kernel.vcproj index 4321eea91..a311252c6 100644 --- a/src/common/kernel.vcproj +++ b/src/common/kernel.vcproj @@ -39,6 +39,7 @@ /> unit; + unsigned int type = shield?ATF_SHIELD:0; unit * u = t.fighter->unit; const armor * a = t.fighter->armors; int geschuetzt = 0; @@ -777,16 +776,13 @@ select_armor(troop t, boolean shield) } for (;a;a=a->next) { - if ((a->atype->flags & ATF_SHIELD)==type) { - geschuetzt += a->count; + if ((a->atype->flags & ATF_SHIELD)==type) { geschuetzt += a->count; if (geschuetzt > t.index) { /* unser Kandidat wird geschuetzt */ return a->atype; } } - } - - return NULL; + } return NULL; } diff --git a/src/common/kernel/eressea.c b/src/common/kernel/eressea.c index f0cc5928e..71f16e2e4 100644 --- a/src/common/kernel/eressea.c +++ b/src/common/kernel/eressea.c @@ -1628,7 +1628,7 @@ cstring(const char *s) } building * -largestbuilding (const region * r, boolean img) +largestbuilding (const region * r, boolean imaginary) { static const building_type * btype = NULL; building *b, *best = NULL; @@ -1638,7 +1638,7 @@ largestbuilding (const region * r, boolean img) for (b = rbuildings(r); b; b = b->next) { if (b->type!=btype) { - if (img) { + if (imaginary) { const attrib * a = a_find(b->attribs, &at_icastle); if (!a) continue; if (a->data.v != btype) continue; diff --git a/src/common/kernel/eressea.h b/src/common/kernel/eressea.h index f41b5d391..dec2d78c8 100644 --- a/src/common/kernel/eressea.h +++ b/src/common/kernel/eressea.h @@ -247,7 +247,7 @@ extern char *cstring_i(char *s); extern const char *unitname(const struct unit * u); extern char * write_unitname(const struct unit * u, char * buffer, size_t size); -struct building *largestbuilding(const struct region * r, boolean img); +struct building *largestbuilding(const struct region * r, boolean imaginary); extern int count_all(const struct faction * f); extern int count_migrants (const struct faction * f); diff --git a/src/common/kernel/move.c b/src/common/kernel/move.c index d48c24fd6..1ae9573dc 100644 --- a/src/common/kernel/move.c +++ b/src/common/kernel/move.c @@ -198,7 +198,7 @@ static boolean entrance_allowed(const struct unit * u, const struct region * r) { #ifdef REGIONOWNERS - faction * owner = region_owner(r); + faction * owner = get_region_owner(r); if (owner == NULL || u->faction == owner) return true; if (alliedfaction(r->planep, owner, u->faction, HELP_TRAVEL)) return true; return false; diff --git a/src/common/kernel/region.c b/src/common/kernel/region.c index d1584368c..98c280f9c 100644 --- a/src/common/kernel/region.c +++ b/src/common/kernel/region.c @@ -1132,6 +1132,8 @@ terraform_region(region * r, const terrain_type * terrain) int mnr = 0; r->land = calloc(1, sizeof(land_region)); + r->land->morale = MORALE_DEFAULT; + r->land->ownership = NULL; region_setname(r, makename()); for (d=0;d!=MAXDIRECTIONS;++d) { region * nr = rconnect(r, d); @@ -1324,24 +1326,21 @@ r_addmessage(struct region * r, const struct faction * viewer, struct message * } struct faction * -region_owner(const struct region * r) +get_region_owner(const struct region * r) { -#ifdef REGIONOWNERS - return r->owner; -#else + if (r->land && r->land->ownership) { + return r->land->ownership->owner; + } return NULL; -#endif } void -region_setowner(struct region * r, struct faction * owner) +set_region_owner(struct region * r, struct faction * owner, int turn) { -#ifdef REGIONOWNERS - r->owner = owner; -#else - unused(r); - unused(owner); -#endif + if (r->land && r->land->ownership) { + r->land->ownership->owner = owner; + r->land->ownership->since_turn = turn; + } } void diff --git a/src/common/kernel/region.h b/src/common/kernel/region.h index 36de5afbb..62041e64a 100644 --- a/src/common/kernel/region.h +++ b/src/common/kernel/region.h @@ -62,6 +62,13 @@ struct rawmaterial; struct donation; struct item; +#define MORALE_DEFAULT 2 /* Morale of peasants that have no lord */ + +typedef struct region_owner { + struct faction * owner; + int since_turn; +} region_owner; + typedef struct land_region { char *name; /* TODO: demand kann nach Konvertierung entfernt werden. */ @@ -72,12 +79,14 @@ typedef struct land_region { } * demands; const struct item_type * herbtype; short herbs; + unsigned short morale; int trees[3]; /* 0 -> seeds, 1 -> shoots, 2 -> trees */ int horses; int peasants; int newpeasants; int money; struct item * items; /* items that can be claimed */ + struct region_owner * ownership; } land_region; typedef struct donation { @@ -112,9 +121,6 @@ typedef struct region { struct donation * donations; const struct terrain_type * terrain; struct rawmaterial * resources; -#ifdef REGIONOWNERS - struct faction * owner; -#endif #ifdef FAST_CONNECT struct region * connect[MAXDIRECTIONS]; /* use rconnect(r, dir) to access */ #endif @@ -226,8 +232,8 @@ extern const short delta_y[MAXDIRECTIONS]; direction_t dir_invert(direction_t dir); int production(const struct region *r); -void region_setowner(struct region * r, struct faction * owner); -struct faction * region_owner(const struct region * r); +void set_region_owner(struct region * r, struct faction * owner, int turn); +struct faction * get_region_owner(const struct region * r); struct region * r_connect(const struct region *, direction_t dir); #ifdef FAST_CONNECT diff --git a/src/common/spells/spells.c b/src/common/spells/spells.c index 4daed5586..e28abbf2e 100644 --- a/src/common/spells/spells.c +++ b/src/common/spells/spells.c @@ -3739,6 +3739,35 @@ sp_analysesong_unit(castorder *co) return cast_level; } + +static boolean +can_charm(const unit * u, int maxlevel) +{ + const skill_t expskills[] = { SK_ALCHEMY, SK_HERBALISM, SK_MAGIC, SK_SPY, SK_TACTICS, NOSKILL }; + skill * sv = u->skills; + + if (fval(u, UFL_HERO)) return false; + + for (;sv!=u->skills+u->skill_size;++sv) { + int l = 0, h = 5; + skill_t sk = sv->id; + assert(expskills[h]==NOSKILL); + while (lfaction, sk)!=INT_MAX) { + return false; + } else if ((int)sv->level>maxlevel) { + return false; + } + break; + } + else if (sk>expskills[m]) l=m+1; + else h=m; + } + } + return true; +} /* ------------------------------------------------------------- */ /* Name: Charming * Stufe: 13 @@ -3789,7 +3818,7 @@ sp_charmingsong(castorder *co) cmistake(mage, co->order, 45, MSG_MAGIC); } /* niemand mit teurem Talent */ - if (has_limited_skills(target)) { + if (!can_charm(target, cast_level/2)) { ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order, "spellfail_noexpensives", "target", target)); return 0; diff --git a/src/common/util.vcproj b/src/common/util.vcproj index 7f93d8fdb..849600b29 100644 --- a/src/common/util.vcproj +++ b/src/common/util.vcproj @@ -39,6 +39,7 @@ /> - - - - - @@ -208,6 +196,10 @@ RelativePath=".\combined\kernel.c" > + + @@ -221,31 +213,6 @@ /> - - - - - - - - @@ -268,10 +235,6 @@ RelativePath=".\combined\stdafx.h" > - - diff --git a/src/eressea/lua/bindings.vcproj b/src/eressea/lua/bindings.vcproj index 9a2674bb7..22acbb366 100644 --- a/src/eressea/lua/bindings.vcproj +++ b/src/eressea/lua/bindings.vcproj @@ -39,6 +39,7 @@ /> +#include +#include +#include #include "tolua/bindings.h" #include "tolua/helpers.h" #include "tolua/bind_unit.h" @@ -129,19 +131,15 @@ #include -/* stdc++ includes */ -#include -#include -#include - /* libc includes */ -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #if defined(_MSC_VER) # include @@ -150,7 +148,6 @@ /** ** global variables we are importing from other modules **/ -extern "C" { extern const char * g_reportdir; extern const char * g_datadir; extern const char * g_basedir; @@ -163,7 +160,6 @@ extern "C" { extern int loadplane; extern boolean opt_cr_absolute_coords; -} /** ** global variables that we are exporting @@ -561,7 +557,7 @@ my_lua_error(lua_State * L) log_error(("A LUA error occured: %s\n", error)); lua_pop(L, 1); - if (!g_ignore_errors) std::terminate(); + if (!g_ignore_errors) abort(); return 1; } @@ -603,8 +599,8 @@ main(int argc, char *argv[]) int i; char * lc_ctype; char * lc_numeric; + lua_State * luaState = lua_init(); - rng_init((unsigned long)time(0)); setup_signal_handler(); sqlpatch = true; @@ -616,7 +612,6 @@ main(int argc, char *argv[]) if (lc_ctype) lc_ctype = strdup(lc_ctype); if (lc_numeric) lc_numeric = strdup(lc_numeric); - lua_State * luaState = lua_init(); global.vm_state = luaState; load_inifile("eressea.ini"); if (verbosity>=4) { diff --git a/src/res/eressea2.xml b/src/res/eressea2.xml index 8ca10bfc7..6ef5faea4 100644 --- a/src/res/eressea2.xml +++ b/src/res/eressea2.xml @@ -104,6 +104,9 @@ + + + diff --git a/src/res/eressea2/terrains.xml b/src/res/eressea2/terrains.xml index 79dab6956..f6a03a496 100644 --- a/src/res/eressea2/terrains.xml +++ b/src/res/eressea2/terrains.xml @@ -1,8 +1,8 @@ - - + + @@ -13,7 +13,7 @@ - + @@ -21,7 +21,7 @@ - + @@ -29,7 +29,7 @@ - + @@ -37,7 +37,7 @@ - + @@ -45,7 +45,7 @@ - + @@ -53,7 +53,7 @@ - + @@ -61,22 +61,22 @@ - + - + - + - + diff --git a/src/scripts/eressea/multis.lua b/src/scripts/eressea/multis.lua index 7e1453a45..4838170c6 100644 --- a/src/scripts/eressea/multis.lua +++ b/src/scripts/eressea/multis.lua @@ -1,3 +1,43 @@ +local function email_multis() + local multis = { + ["u9bx"]="Tachlaar@web.de", + ["7Lwz"]="Tachlaar@web.de", + ["ddr"]="Tachlaar@web.de", + ["myrd"]="Tachlaar@web.de", + ["2a4v"]="Samurai_krieger@web.de", + ["7oiw"]="Samurai_krieger@web.de", + ["brud"]="Samurai_krieger@web.de", + ["bzcm"]="Samurai_krieger@web.de", + ["crow"]="Samurai_krieger@web.de", + ["dino"]="Samurai_krieger@web.de", + ["fynd"]="Samurai_krieger@web.de", + ["Leer"]="Samurai_krieger@web.de", + ["moos"]="Samurai_krieger@web.de", + ["ogcL"]="Samurai_krieger@web.de", + ["paty"]="Samurai_krieger@web.de", + ["rd"]="Samurai_krieger@web.de", + ["seee"]="Samurai_krieger@web.de", + ["szem"]="Samurai_krieger@web.de", + ["uebL"]="Samurai_krieger@web.de", + ["uvzp"]="Samurai_krieger@web.de", + ["wzLp"]="Samurai_krieger@web.de", + ["ziwe"]="Samurai_krieger@web.de" + } + local k + local v + for k, info in pairs(multis) do + local f = get_faction(atoi36(k)) + if f~=nil then + print("- marking " .. tostring(f) .. " as a multi-player.") + f.email = v + f.password = "" + f.info = info + else + print("- could not find faction " .. k) + end + end +end + local function kill_multis() local multis = { ["u9bx"]="Doppelspiel-Partei von Tachlaar@web.de", @@ -39,4 +79,4 @@ local function kill_multis() end print("killing multi-players") -kill_multis() +email_multis()