new implementation blessedharvest and raindance (in lua)

lots of lua interfacing for spells.
region.adj (Lua) is kewl.
This commit is contained in:
Enno Rehling 2009-07-23 19:19:01 +00:00
parent c175a8dcea
commit bc3612935b
15 changed files with 200 additions and 71 deletions

View file

@ -1497,7 +1497,7 @@ region_getname(const region * r) {
int region_get_morale(const region * r)
{
return r->land?r->land->morale:0;
return r->land?r->land->morale:-1;
}
void region_set_morale(region * r, int morale)

View file

@ -2088,6 +2088,50 @@ static void log_orders(const struct message * msg)
}
}
int
report_action(region * r, unit * actor, message * msg, int flags)
{
int result = 0;
unit * u;
int view = flags&(ACTION_CANSEE|ACTION_CANNOTSEE);
/* melden, 1x pro Partei */
if (flags&ACTION_RESET) {
freset(actor->faction, FFL_SELECT);
for (u = r->units; u; u = u->next ) freset(u->faction, FFL_SELECT);
}
if (view) {
for (u = r->units; u; u = u->next ) {
if (!fval(u->faction, FFL_SELECT) ) {
boolean show = u->faction == actor->faction;
fset(u->faction, FFL_SELECT);
if (view==ACTION_CANSEE) {
/* Bei Fernzaubern sieht nur die eigene Partei den Magier */
show = show || (r==actor->region && cansee(u->faction, r, actor, 0));
} else if (view==ACTION_CANNOTSEE) {
show = !show && !(r==actor->region && cansee(u->faction, r, actor, 0));
} else {
/* the unliely (or lazy) case */
show = true;
}
if (show) {
r_addmessage(r, u->faction, msg);
} else { /* Partei des Magiers, sieht diesen immer */
result = 1;
}
}
}
/* Ist niemand von der Partei des Magiers in der Region, dem Magier
* nochmal gesondert melden */
if ((flags&ACTION_CANSEE) && !fval(actor->faction, FFL_SELECT)) {
add_message(&actor->faction->msgs, msg);
}
}
return result;
}
void
reports_init(void)
{

View file

@ -126,6 +126,11 @@ extern const char * report_kampfstatus(const struct unit * u, const struct local
void report_building(const struct building * b, const char ** btype, const char ** billusion);
void report_race(const struct unit * u, const char ** rcname, const char ** rcillusion);
#define ACTION_RESET 0x01 /* reset the one-time-flag FFL_SELECT (on first pass) */
#define ACTION_CANSEE 0x02 /* to people who can see the actor */
#define ACTION_CANNOTSEE 0x04 /* to people who can not see the actor */
extern int report_action(struct region * r, struct unit * actor, struct message * msg, int flags);
extern size_t f_regionid(const struct region * r, const struct faction * f, char * buffer, size_t size);
extern const char * combatstatus[];

View file

@ -35,9 +35,7 @@ enum {
SPL_BERSERK,
SPL_BLOODTHIRST,
SPL_MAELSTROM,
SPL_BLESSEDHARVEST,
SPL_RAINDANCE,
SPL_TRANSFERAURA_DRUIDE,
SPL_TRANSFERAURA_DRUIDE = 27,
SPL_TRANSFERAURA_BARDE,
SPL_TRANSFERAURA_CHAOS,
SPL_TRANSFERAURA_TRAUM,

View file

@ -1205,9 +1205,9 @@ item_modification(const unit *u, skill_t sk, int val)
static int
att_modification(const unit *u, skill_t sk)
{
int bonus = 0, malus = 0;
double bonus = 0, malus = 0;
attrib * a;
int result = 0;
double result = 0;
static boolean init = false;
static const curse_type * skillmod_ct, * gbdream_ct, * worse_ct;
curse * c;
@ -1240,7 +1240,7 @@ att_modification(const unit *u, skill_t sk)
while (a && a->type==&at_curse) {
curse * c = (curse*)a->data.v;
if (curse_active(c) && c->type==gbdream_ct) {
int mod = curse_geteffect(c);
double mod = curse_geteffect(c);
unit * mage = c->magician;
/* wir suchen jeweils den größten Bonus und den größten Malus */
if (mod>bonus) {
@ -1257,7 +1257,7 @@ att_modification(const unit *u, skill_t sk)
}
result = result + bonus + malus;
return result;
return (int)result;
}
int

View file

@ -31,6 +31,7 @@
#include <kernel/curse.h>
#include <kernel/spellid.h>
#include <kernel/faction.h>
#include <kernel/reports.h>
#include <kernel/item.h>
#include <kernel/karma.h>
#include <kernel/magic.h>
@ -380,9 +381,11 @@ break_curse(attrib **alist, int cast_level, double force, curse * c)
/* ------------------------------------------------------------- */
/* Report a spell's effect to the units in the region.
*/
static void
report_effect(region * r, unit * mage, message * seen, message * unseen)
{
#if 0
unit * u;
/* melden, 1x pro Partei */
@ -415,6 +418,12 @@ report_effect(region * r, unit * mage, message * seen, message * unseen)
if (!fval(mage->faction, FFL_SELECT)) {
add_message(&mage->faction->msgs, seen);
}
#else
int err = report_action(r, mage, seen, ACTION_RESET|ACTION_CANSEE);
if (err) {
report_action(r, mage, seen, ACTION_CANNOTSEE);
}
#endif
}
/* ------------------------------------------------------------- */
@ -1086,40 +1095,17 @@ sp_blessedharvest(castorder *co)
unit *mage = co->magician.u;
int cast_level = co->level;
double power = co->force;
double effect;
int rule = rule_blessed_harvest();
int duration = (int)power+1;
/* Attribut auf Region.
* Existiert schon ein curse, so wird dieser verstärkt
* (Max(Dauer), Max(Stärke))*/
if (rule==HARVEST_WORK) {
int duration = (int)power+1;
effect = 1;
create_curse(mage, &r->attribs, ct_find("blessedharvest"), power, duration, effect, 0);
} else if (rule==HARVEST_TAXES) {
int duration = (int)(power*2);
if (co->sp->id!=SPL_BLESSEDHARVEST) {
effect = (int)(100 * power);
create_curse(mage, &r->attribs, ct_find("blessedharvest"), power, duration, effect, 0);
} else {
int d;
region * rn[MAXDIRECTIONS];
get_neighbours(r, rn);
effect = (int)(50 * power);
for (d=0;d!=MAXDIRECTIONS;++d) {
region * rx = rn[d];
if (rx && rx->land) {
create_curse(mage, &rx->attribs, ct_find("blessedharvest"), power, duration, effect, 0);
}
}
create_curse(mage, &r->attribs, ct_find("blessedharvest"), power, duration, effect, 0);
}
}
{
message * seen = msg_message("harvest_effect", "mage", mage);
message * unseen = msg_message("harvest_effect", "mage", NULL);
report_effect(r, mage, seen, unseen);
msg_release(seen);
msg_release(unseen);
if (create_curse(mage, &r->attribs, ct_find("blessedharvest"), power, duration, 1.0, 0)) {
message * seen = msg_message("harvest_effect", "mage", mage);
message * unseen = msg_message("harvest_effect", "mage", NULL);
report_effect(r, mage, seen, unseen);
msg_release(seen);
msg_release(unseen);
}
return cast_level;
@ -6869,20 +6855,6 @@ typedef struct spelldata {
static spelldata spelldaten[] =
{
/* M_GWYRRD */
{
SPL_BLESSEDHARVEST, "blessedharvest", NULL, NULL, NULL,
M_GWYRRD,
(FARCASTING | SPELLLEVEL | ONSHIPCAST | REGIONSPELL),
5, 1,
{
{ "aura", 1, SPC_LEVEL },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 }
},
(spell_f)sp_blessedharvest, NULL
},
{
SPL_STONEGOLEM, "stonegolem", NULL, NULL, NULL,
M_GWYRRD, (SPELLLEVEL), 4, 1,
@ -7937,20 +7909,6 @@ static spelldata spelldaten[] =
},
(spell_f)sp_generous, NULL
},
{
SPL_RAINDANCE, "raindance", NULL, NULL, NULL,
M_CERDDOR,
(FARCASTING | SPELLLEVEL | ONSHIPCAST | REGIONSPELL),
5, 3,
{
{ "aura", 1, SPC_LEVEL },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 }
},
(spell_f)sp_blessedharvest, NULL
},
{
SPL_SONG_OF_FEAR, "song_of_fear", NULL, NULL, NULL,
M_CERDDOR, (COMBATSPELL | SPELLLEVEL), 5, 3,
@ -8933,6 +8891,7 @@ register_spells(void)
register_regioncurse();
register_shipcurse();
register_buildingcurse();
register_function((pf_generic)&sp_blessedharvest, "cast_blessedharvest");
register_function((pf_generic)&sp_wdwpyramid, "wdwpyramid");
register_function((pf_generic)&sp_summon_familiar, "cast_familiar");
}

View file

@ -5,6 +5,7 @@
#include <kernel/faction.h>
#include <kernel/item.h>
#include <kernel/message.h>
#include <kernel/reports.h>
#include <kernel/region.h>
#include <kernel/unit.h>
@ -282,6 +283,18 @@ tolua_msg_send_region(lua_State * L)
return 1;
}
static int
tolua_msg_report_action(lua_State * L)
{
lua_message * lmsg = (lua_message *)tolua_tousertype(L, 1, 0);
region * r = (region *)tolua_tousertype(L, 2, 0);
unit * u = (unit *)tolua_tousertype(L, 3, 0);
int flags = (int)tolua_tonumber(L, 4, 0);
int result = report_action(r, u, lmsg->msg, flags);
tolua_pushnumber(L, (lua_Number)result);
return 1;
}
static int
tolua_msg_send_faction(lua_State * L)
{
@ -314,6 +327,7 @@ tolua_message_open(lua_State* L)
tolua_function(L, TOLUA_CAST "set_string", tolua_msg_set_string);
tolua_function(L, TOLUA_CAST "send_faction", tolua_msg_send_faction);
tolua_function(L, TOLUA_CAST "send_region", tolua_msg_send_region);
tolua_function(L, TOLUA_CAST "report_action", tolua_msg_report_action);
tolua_function(L, TOLUA_CAST "create", tolua_msg_create);
}

View file

@ -208,6 +208,23 @@ static int tolua_region_get_flag(lua_State* L)
}
static int tolua_region_get_adj(lua_State* L)
{
region* r = (region*)tolua_tousertype(L, 1, 0);
region* rn[MAXDIRECTIONS];
int d, idx;
get_neighbours(r, rn);
lua_createtable(L, MAXDIRECTIONS, 0);
for (d=0,idx=0;d!=MAXDIRECTIONS;++d) {
if (rn[d]) {
tolua_pushusertype(L, rn[d], TOLUA_CAST "region");
lua_rawseti(L, -2, ++idx);
}
}
return 1;
}
static int tolua_region_get_next(lua_State* L)
{
region* self = (region*)tolua_tousertype(L, 1, 0);
direction_t dir = (direction_t)tolua_tonumber(L, 2, 0);
@ -573,7 +590,8 @@ tolua_region_open(lua_State* L)
tolua_function(L, TOLUA_CAST "set_resource", tolua_region_set_resource);
tolua_function(L, TOLUA_CAST "get_flag", tolua_region_get_flag);
tolua_function(L, TOLUA_CAST "set_flag", tolua_region_set_flag);
tolua_function(L, TOLUA_CAST "next", tolua_region_get_adj);
tolua_function(L, TOLUA_CAST "next", tolua_region_get_next);
tolua_variable(L, TOLUA_CAST "adj", tolua_region_get_adj, NULL);
tolua_variable(L, TOLUA_CAST "terrain_name", &tolua_region_get_terrainname, &tolua_region_set_terrainname);
tolua_variable(L, TOLUA_CAST "owner", &tolua_region_get_owner, &tolua_region_set_owner);

View file

@ -328,6 +328,46 @@ tolua_get_season(lua_State * L)
return 1;
}
static int
tolua_create_curse(lua_State * L)
{
unit * u = (unit *)tolua_tousertype(L, 1, 0);
tolua_Error tolua_err;
attrib ** ap = NULL;
if (tolua_isusertype(L, 2, TOLUA_CAST "unit", 0, &tolua_err)) {
unit * target = (unit *)tolua_tousertype(L, 1, 0);
if (target) ap = &target->attribs;
} else if (tolua_isusertype(L, 2, TOLUA_CAST "region", 0, &tolua_err)) {
region * target = (region *)tolua_tousertype(L, 1, 0);
if (target) ap = &target->attribs;
} else if (tolua_isusertype(L, 2, TOLUA_CAST "ship", 0, &tolua_err)) {
ship * target = (ship *)tolua_tousertype(L, 1, 0);
if (target) ap = &target->attribs;
} else if (tolua_isusertype(L, 2, TOLUA_CAST "building", 0, &tolua_err)) {
building * target = (building *)tolua_tousertype(L, 1, 0);
if (target) ap = &target->attribs;
}
if (ap) {
const char * cname = tolua_tostring(L, 3, 0);
const curse_type * ctype = ct_find(cname);
if (ctype) {
double vigour = tolua_tonumber(L, 4, 0);
int duration = (int)tolua_tonumber(L, 5, 0);
double effect = tolua_tonumber(L, 6, 0);
int men = (int)tolua_tonumber(L, 7, 0); /* optional */
curse * c = create_curse(u, ap, ctype, vigour, duration, effect, men);
if (c) {
tolua_pushboolean(L, true);
return 1;
}
}
}
tolua_pushboolean(L, false);
return 1;
}
static int
tolua_learn_skill(lua_State * L)
{
@ -970,6 +1010,7 @@ tolua_eressea_open(lua_State* L)
tolua_function(L, TOLUA_CAST "update_owners", tolua_update_owners);
tolua_function(L, TOLUA_CAST "learn_skill", tolua_learn_skill);
tolua_function(L, TOLUA_CAST "create_curse", tolua_create_curse);
tolua_function(L, TOLUA_CAST "autoseed", tolua_autoseed);

View file

@ -28,6 +28,7 @@
<xi:include href="e3a/calendar.xml"/>
<xi:include href="e3a/items.xml" />
<xi:include href="e3a/strings.xml"/>
<xi:include href="e3a/messages.xml"/>
<xi:include href="e3a/races.xml"/>
<xi:include href="e3a/buildings.xml"/>
<xi:include href="e3a/equipment.xml"/>

View file

@ -278,6 +278,7 @@
<!-- new gwyrrd -->
<spell name="blessedharvest" type="gwyrrd" rank="5" level="3" index="25" ship="true" far="true" variable="true">
<!-- Segen der Erde -->
<function name="cast" value="lua_castspell"/>
<resource name="aura" amount="1" cost="level"/>
</spell>
<spell name="earn_silver#gwyrrd" type="gwyrrd" ship="true" variable="true" rank="5" level="1" index="159">
@ -504,6 +505,7 @@
</spell>
<spell name="raindance" type="common" rank="5" level="2" index="26" ship="true" far="true" variable="true">
<!-- Regentanz -->
<function name="cast" value="lua_castspell"/>
<resource name="aura" amount="1" cost="level"/>
</spell>
<spell name="irongolem" type="common" rank="4" level="2" index="33" variable="true">

View file

@ -35,6 +35,12 @@
</spell>
<!-- gwyrrd spells -->
<spell name="blessedharvest" type="gwyrrd" rank="5" level="1" index="25" ship="true" far="true" variable="true">
<!-- Segen der Erde -->
<function name="cast" value="cast_blessedharvest"/>
<resource name="aura" amount="1" cost="level"/>
</spell>
<spell name="create_roi" type="gwyrrd" ship="true" rank="5" level="6" index="129">
<function name="cast" value="lua_castspell"/>
<resource name="aura" amount="50" cost="fixed"/>
@ -95,6 +101,11 @@
</spell>
<!-- cerddor spells -->
<spell name="raindance" type="cerddor" rank="5" level="3" index="26" ship="true" far="true" variable="true">
<!-- Segen der Erde -->
<function name="cast" value="cast_blessedharvest"/>
<resource name="aura" amount="1" cost="level"/>
</spell>
<spell name="create_roi" type="cerddor" ship="true" rank="5" level="6" index="132">
<function name="cast" value="lua_castspell"/>
<resource name="aura" amount="50" cost="fixed"/>

View file

@ -40,3 +40,39 @@ function building_taxes(b, blevel)
end
return 0.0
end
-- the "raindance" spell
function raindance(r, mage, level, force)
if (create_curse(mage, r, "blessedharvest", force, force*2, 100 * force)) then
-- slightly crooked way of reporting an action to everyone in the region
local msg = message.create("raindance_effect")
msg:set_unit("mage", mage)
if (msg:report_action(r, mage, 3)) then
local msg2 = message.create("raindance_effect")
msg2:set_unit("mage", nil)
msg2:report_action(r, mage, 4)
end
end
return level
end
-- the "blessed harvest" spell
function blessedharvest(r, mage, level, force)
if create_curse(mage, r, "blessedharvest", force, force*2, 50 * force) then
-- slightly crooked way of reporting an action to everyone in the region
local msg = message.create("harvest_effect")
msg:set_unit("mage", mage)
if (msg:report_action(r, mage, 3)) then
local msg2 = message.create("harvest_effect")
msg2:set_unit("mage", nil)
msg2:report_action(r, mage, 4)
end
for idx, rn in ipairs(r.adj) do
-- nur landregionen haben moral>=0
if r.morale>=0 then
create_curse(mage, r, "blessedharvest", force, force*2, 50 * force)
end
end
end
return level
end

View file

@ -1,5 +1,5 @@
function creation_message(mage, type)
msg = message.create("item_create_spell")
local msg = message.create("item_create_spell")
msg:set_unit("mage", mage)
msg:set_int("number", 1)
msg:set_resource("item", type)

View file

@ -433,7 +433,7 @@ function test_taxes()
local u = unit.create(f, r, 1)
u:add_item("money", u.number * 10)
u:clear_orders()
u:add_order("LERNE Wahrnehmung")
u:add_order("LERNE Holzfällen") -- do not work
local b = building.create(r, "watch")
b.size = 10
u.building = b
@ -652,7 +652,7 @@ mytests = {
-- ["blessed"] = test_blessed -- foiled by peasantgrowth
}
fail = 0
for k, v in pairs(mytests) do
for k, v in pairs(tests) do
local status, err = pcall(v)
if not status then
fail = fail + 1