2001-01-25 10:37:55 +01:00
/* vi: set ts=2:
*
* Eressea PB ( E ) M host Copyright ( C ) 1998 - 2000
* Christian Schlittchen ( corwin @ amber . kn - bremen . de )
* Katja Zedel ( katze @ felidae . kn - bremen . de )
* Henning Peters ( faroul @ beyond . kn - bremen . de )
* Enno Rehling ( enno @ eressea - pbem . de )
* Ingo Wilken ( Ingo . Wilken @ informatik . uni - oldenburg . de )
*
* based on :
*
* Atlantis v1 .0 13 September 1993 Copyright 1993 by Russell Wallace
* Atlantis v1 .7 Copyright 1996 by Alex Schr <EFBFBD> der
*
* This program may not be used , modified or distributed without
* prior permission by the authors of Eressea .
* This program may not be sold or used commercially without prior written
* permission from the authors .
*/
# include <config.h>
# include <eressea.h>
2001-05-11 22:19:22 +02:00
/* misc includes */
# include <attributes/key.h>
2001-01-25 10:37:55 +01:00
# include <modules/xmas2000.h>
2001-12-30 09:24:05 +01:00
# include <modules/xmas2001.h>
2001-01-25 10:37:55 +01:00
# include <modules/museum.h>
2002-04-27 21:40:31 +02:00
# include <modules/xecmd.h>
2002-04-27 16:25:35 +02:00
# include <items/questkeys.h>
2001-01-25 10:37:55 +01:00
/* gamecode includes */
# include <creation.h>
# include <economy.h>
/* kernel includes */
# include <border.h>
# include <building.h>
2001-02-13 00:06:44 +01:00
# include <ship.h>
2001-01-25 10:37:55 +01:00
# include <faction.h>
# include <item.h>
# include <magic.h>
# include <message.h>
# include <monster.h>
# include <movement.h>
# include <names.h>
# include <pathfinder.h>
# include <plane.h>
# include <pool.h>
# include <race.h>
# include <region.h>
# include <reports.h>
2001-12-10 01:13:39 +01:00
# include <resources.h>
2001-01-25 10:37:55 +01:00
# include <skill.h>
# include <teleport.h>
# include <unit.h>
# include <spell.h>
2001-12-10 01:13:39 +01:00
# include <alchemy.h>
# include <study.h>
2001-01-25 10:37:55 +01:00
/* util includes */
# include <attrib.h>
# include <base36.h>
# include <cvector.h>
2001-12-10 01:13:39 +01:00
# include <event.h>
2002-05-05 11:37:43 +02:00
# include <goodies.h>
2001-01-25 10:37:55 +01:00
# include <resolve.h>
2001-12-10 01:13:39 +01:00
# include <sql.h>
2001-01-25 10:37:55 +01:00
# include <vset.h>
/* libc includes */
# include <stdio.h>
2002-03-09 16:16:35 +01:00
# include <ctype.h>
2001-01-25 10:37:55 +01:00
# include <stdlib.h>
# include <string.h>
/* attributes includes */
# include <attributes/targetregion.h>
# include <attributes/key.h>
2001-12-30 09:24:05 +01:00
# undef XMAS1999
# undef XMAS2000
2002-02-03 03:36:12 +01:00
# undef XMAS2001
2001-12-10 01:13:39 +01:00
2001-02-13 00:06:44 +01:00
extern void reorder_owners ( struct region * r ) ;
2002-05-02 23:19:45 +02:00
static int
convert_orders ( void )
{
region * r ;
for ( r = regions ; r ; r = r - > next ) {
unit * u ;
for ( u = r - > units ; u ; u = u - > next ) {
strlist * o ;
for ( o = u - > orders ; o ; o = o - > next ) {
int c = igetkeyword ( o - > s , u - > faction - > locale ) ;
switch ( c ) {
case K_RESERVE :
case K_BUY :
case K_SELL :
case K_CAST :
sprintf ( buf , " @%s " , LOC ( u - > faction - > locale , keywords [ c ] ) ) ;
for ( ; ; ) {
const char * c = getstrtoken ( ) ;
if ( c & & * c ) {
2002-05-05 11:37:43 +02:00
char * p = strchr ( c , ' ' ) ;
if ( p ) {
char zText [ 128 ] ;
c = strcpy ( zText , c ) ;
space_replace ( zText , SPACE_REPLACEMENT ) ;
2002-05-02 23:19:45 +02:00
}
2002-05-05 11:37:43 +02:00
strcat ( buf , " " ) ;
strcat ( buf , c ) ;
2002-05-02 23:19:45 +02:00
} else break ;
}
set_string ( & o - > s , buf ) ;
break ;
}
}
}
}
return 0 ;
}
2001-02-13 00:06:44 +01:00
static void
verify_owners ( boolean bOnce )
{
region * r ;
for ( r = regions ; r ; r = r - > next ) {
unit * u ;
boolean bFail = false ;
for ( u = r - > units ; u ; u = u - > next ) {
if ( u - > building ) {
unit * bo = buildingowner ( r , u - > building ) ;
if ( ! fval ( bo , FL_OWNER ) ) {
log_error ( ( " [verify_owners] %u ist Besitzer von %s, hat aber FL_OWNER nicht. \n " , unitname ( bo ) , buildingname ( u - > building ) ) ) ;
bFail = true ;
if ( bOnce ) break ;
}
2001-02-13 00:13:14 +01:00
if ( bo ! = u & & fval ( u , FL_OWNER ) ) {
2001-02-13 00:06:44 +01:00
log_error ( ( " [verify_owners] %u ist NICHT Besitzer von %s, hat aber FL_OWNER. \n " , unitname ( u ) , buildingname ( u - > building ) ) ) ;
bFail = true ;
if ( bOnce ) break ;
}
}
if ( u - > ship ) {
unit * bo = shipowner ( r , u - > ship ) ;
if ( ! fval ( bo , FL_OWNER ) ) {
log_error ( ( " [verify_owners] %u ist Besitzer von %s, hat aber FL_OWNER nicht. \n " , unitname ( bo ) , shipname ( u - > ship ) ) ) ;
bFail = true ;
if ( bOnce ) break ;
}
2001-02-13 00:13:14 +01:00
if ( bo ! = u & & fval ( u , FL_OWNER ) ) {
2001-02-13 00:06:44 +01:00
log_error ( ( " [verify_owners] %u ist NICHT Besitzer von %s, hat aber FL_OWNER. \n " , unitname ( u ) , shipname ( u - > ship ) ) ) ;
bFail = true ;
if ( bOnce ) break ;
}
}
}
if ( bFail ) reorder_owners ( r ) ;
}
}
2001-02-02 09:40:49 +01:00
/* make sure that this is done only once! */
# define do_once(magic, fun) \
{ \
2001-09-05 21:40:40 +02:00
attrib * a = find_key ( global . attribs , atoi36 ( magic ) ) ; \
2002-04-07 02:44:01 +02:00
if ( ! a ) { \
log_warning ( ( " [do_once] a unique fix %d= \" %s \" was applied. \n " , atoi36 ( magic ) , magic ) ) ; \
2001-12-10 01:13:39 +01:00
if ( fun = = 0 ) a_add ( & global . attribs , make_key ( atoi36 ( magic ) ) ) ; \
2001-02-20 23:54:05 +01:00
} \
2001-01-25 10:37:55 +01:00
}
2002-03-10 11:09:16 +01:00
int
warn_items ( void )
{
boolean found = 0 ;
region * r ;
2002-04-07 02:44:01 +02:00
const item_type * it_money = it_find ( " money " ) ;
2002-03-10 11:09:16 +01:00
for ( r = regions ; r ; r = r - > next ) {
unit * u ;
for ( u = r - > units ; u ; u = u - > next ) {
item * itm ;
for ( itm = u - > items ; itm ; itm = itm - > next ) {
2002-04-07 02:44:01 +02:00
if ( itm - > number > 100000 & & itm - > type ! = it_money ) {
2002-03-10 11:09:16 +01:00
found = 1 ;
2002-05-02 23:19:45 +02:00
log_error ( ( " Einheit %s hat %u %s \n " ,
unitid ( u ) , itm - > number ,
2002-03-10 11:09:16 +01:00
resourcename ( itm - > type - > rtype , 0 ) ) ) ;
2001-01-25 10:37:55 +01:00
}
}
}
}
2002-03-10 11:09:16 +01:00
return found ;
2001-01-25 10:37:55 +01:00
}
2001-12-30 09:24:05 +01:00
# ifdef XMAS1999
2001-01-25 10:37:55 +01:00
# include "race.h"
# include "movement.h"
static void
santa_comes_to_town ( void )
{
unit * santa = ufindhash ( atoi36 ( " xmas " ) ) ;
unit * tans = ufindhash ( atoi36 ( " tans " ) ) ;
faction * f ;
region * r ;
if ( ! tans ) r = findregion ( 0 , 0 ) ;
else r = tans - > region ;
if ( ! r ) return ;
while ( santa & & santa - > race ! = RC_ILLUSION ) {
uunhash ( santa ) ;
santa - > no = newunitid ( ) ;
uhash ( santa ) ;
santa = ufindhash ( atoi36 ( " xmas " ) ) ;
}
if ( ! santa ) {
2001-12-10 01:13:39 +01:00
santa = createunit ( r , findfaction ( MONSTER_FACTION ) , 1 , new_race [ RC_ILLUSION ] ) ;
2001-01-25 10:37:55 +01:00
uunhash ( santa ) ;
santa - > no = atoi36 ( " xmas " ) ;
uhash ( santa ) ;
}
santa - > age = 2 ;
2001-12-10 01:13:39 +01:00
santa - > irace = new_race [ RC_DAEMON ] ;
2001-01-25 10:37:55 +01:00
set_string ( & santa - > name , " Ein dicker Gnom mit einem Rentierschlitten " ) ;
set_string ( & santa - > display , " hat: 6 Rentiere, Schlitten, Sack mit Geschenken, Kekse f<> r Khorne " ) ;
for ( f = factions ; f ; f = f - > next ) {
unit * u ;
runit * ru ;
region * r ;
item_t i = ( item_t ) ( rand ( ) % 4 + I_KEKS ) ;
unit * senior = f - > units ;
for ( u = f - > units ; u ; u = u - > nextF ) {
if ( senior - > age < u - > age ) senior = u ;
}
if ( ! senior ) continue ;
r = senior - > region ;
sprintf ( buf , " %s gibt %d %s an %s. " , unitname ( santa ) , 1 , itemdata [ i ] . name [ 0 ] , unitname ( senior ) ) ;
change_item ( senior , i , 1 ) ;
addmessage ( r , senior - > faction , buf , MSG_COMMERCE , ML_INFO ) ;
sprintf ( buf , " von %s: 'Ho ho ho. Frohe Weihnachten, und %s f<> r %s.' " , unitname ( santa ) , itemdata [ i ] . name [ 1 ] , unitname ( senior ) ) ;
addmessage ( r , 0 , buf , MSG_MESSAGE , ML_IMPORTANT ) ;
for ( ru = r - > durchgezogen ; ru ; ru = ru - > next )
if ( ru - > unit = = santa ) break ;
if ( ! ru ) {
ru = calloc ( 1 , sizeof ( runit ) ) ;
ru - > next = r - > durchgezogen ;
ru - > unit = santa ;
r - > durchgezogen = ru ;
}
}
}
# endif
#if 0
static void
init_hp ( void )
{
region * r ;
unit * u ;
for ( r = regions ; r ; r = r - > next ) {
for ( u = r - > units ; u ; u = u - > next ) {
if ( u - > hp = = - 1 ) {
u - > hp = unit_max_hp ( u ) * u - > number ;
}
}
}
}
static void
convert ( int x , int y , int * nx , int * ny )
{
* ny = - y ;
* nx = x + ( y + ( ( y > = 0 ) ? 1 : 0 ) ) / 2 ;
}
# endif
#if 0
static void
loesche_coasts ( void )
{
region * r ;
ship * sh ;
for ( r = regions ; r ; r = r - > next ) {
for ( sh = r - > ships ; sh ; sh = sh - > next ) {
sh - > coast = NODIRECTION ;
}
}
}
# endif
#if 0
static void
create_underworld ( void )
{
int x , y ;
region * r ;
attrib * a ;
2002-01-28 01:25:32 +01:00
plane * hell = create_new_plane ( - 1 , " H<EFBFBD> lle " , 100000 , 100000 , 100020 , 100020 , PFL_NONE ) ;
2001-01-25 10:37:55 +01:00
for ( x = 0 ; x < = 20 ; x + + ) {
for ( y = 0 ; y < = 20 ; y + + ) {
r = new_region ( x + 100000 , y ) ;
r - > planep = hell ;
if ( x = = 0 | | x = = 20 | | y = = 0 | | y = = 20 ) {
rsetterrain ( r , T_FIREWALL ) ;
} else {
rsetterrain ( r , T_HELL ) ;
}
}
}
/* Verbindungen schaffen */
a = create_special_direction ( findregion ( 4 , 4 ) , 100005 , 5 , - 1 ,
" Ein dunkler Schlund fuehrt in die Tiefe der Erde " ,
" Schlund " ) ;
a = create_special_direction ( findregion ( 100005 , 5 ) , 4 , 4 , - 1 ,
" Ein hell erleuchteter Tunnel fuehrt nach oben " ,
" Tunnel " ) ;
}
# endif
#if 0
static void
bename_dracoide ( void )
{
region * r ;
unit * u ;
for ( r = regions ; r ; r = r - > next ) {
for ( u = r - > units ; u ; u = u - > next ) {
2001-12-10 01:13:39 +01:00
if ( u - > race = = new_race [ RC_DRACOID ] ) name_unit ( u ) ;
2001-01-25 10:37:55 +01:00
}
}
}
# endif
static void
fix_migrants ( void ) {
region * r ;
for ( r = regions ; r ; r = r - > next ) {
unit * u ;
for ( u = r - > units ; u ; u = u - > next ) {
2001-12-10 01:13:39 +01:00
if ( u - > race = = new_race [ RC_HUMAN ] ) u - > irace = u - > race ;
if ( u - > irace ! = u - > race & & ( u - > race - > flags & RCF_SHAPESHIFT ) = = 0 ) {
2002-01-05 17:14:38 +01:00
log_warning ( ( " [fix_migrants] %s ist ein %s, als %s getarnt \n " , unitname ( u ) , LOC ( default_locale , rc_name ( u - > race , 0 ) ) , LOC ( default_locale , rc_name ( u - > irace , 0 ) ) ) ) ;
2001-01-25 10:37:55 +01:00
}
}
}
}
static boolean
kor_teure_talente ( unit * u )
{
if ( effskill ( u , SK_TACTICS ) > = 1 | |
effskill ( u , SK_MAGIC ) > = 1 | |
effskill ( u , SK_ALCHEMY ) > = 1 | |
effskill ( u , SK_HERBALISM ) > = 1 | |
effskill ( u , SK_SPY ) > = 1 ) {
return true ;
}
return false ;
}
static void
no_teurefremde ( boolean convert )
{
region * r ;
unit * u ;
for ( r = regions ; r ; r = r - > next ) {
for ( u = r - > units ; u ; u = u - > next ) {
if ( u - > faction - > no ! = MONSTER_FACTION
2001-12-10 01:13:39 +01:00
& & is_migrant ( u )
2002-05-02 23:19:45 +02:00
& & kor_teure_talente ( u ) )
2001-12-10 01:13:39 +01:00
{
2002-05-02 23:19:45 +02:00
log_printf ( " * Warnung, teurer Migrant: %s %s \n " ,
2001-12-10 01:13:39 +01:00
unitname ( u ) , factionname ( u - > faction ) ) ;
2001-01-25 10:37:55 +01:00
if ( convert ) {
u - > race = u - > faction - > race ;
2001-12-10 01:13:39 +01:00
u - > irace = u - > faction - > race ;
2001-01-25 10:37:55 +01:00
u - > faction - > num_migrants - = u - > number ;
2001-12-10 01:13:39 +01:00
sprintf ( buf , " Die G<> tter segnen %s mit der richtigen Rasse " ,
unitname ( u ) ) ;
addmessage ( 0 , u - > faction , buf , MSG_MESSAGE , ML_IMPORTANT ) ;
2001-01-25 10:37:55 +01:00
}
}
}
}
}
#if 0
static void
give_arena_gates ( void )
{
faction * f ;
for ( f = factions ; f ; f = f - > next ) {
unit * u ;
region * r ;
unit * senior = f - > units ;
if ( f - > age > 2 ) return ;
for ( u = f - > units ; u ; u = u - > nextF ) {
if ( senior - > age < u - > age ) senior = u ;
if ( f - > no = = MONSTER_FACTION & & get_item ( u , I_ARENA_GATE ) ) return ;
}
if ( ! senior ) continue ;
r = senior - > region ;
sprintf ( buf , " Der Himmel <20> ber %s rei<65> t auf und ein Licht aus den Wolken scheint auf %s. Ein Gesang wie von tausend Walk<6C> ren ert<72> nt, dazu Schlachtenl<6E> rm. Nach einer Weile endet die Vision, und %s h<> lt ein %s in den H<> nden. " , regionid ( senior - > region ) , unitname ( senior ) , unitname ( senior ) , itemdata [ I_ARENA_GATE ] . name [ 0 ] ) ;
change_item ( senior , I_ARENA_GATE , 1 ) ;
addmessage ( NULL , senior - > faction , buf , MSG_MESSAGE , ML_IMPORTANT ) ;
}
}
static void
remove_impossible_dragontargets ( void )
{
region * r ;
for ( r = regions ; r ; r = r - > next ) {
unit * u ;
for ( u = r - > units ; u ; u = u - > next ) {
2001-02-02 09:40:49 +01:00
attrib * a ;
2001-01-25 10:37:55 +01:00
if ( u - > faction - > no ! = MONSTER_FACTION ) continue ;
2001-02-02 09:40:49 +01:00
a = a_find ( u - > attribs , & at_targetregion ) ;
2001-01-25 10:37:55 +01:00
if ( a ! = NULL ) {
boolean cango = false ;
region * r2 = a - > data . v ;
if ( r2 ! = NULL ) {
# ifdef NEW_PATH
cango = path_exists ( r , r2 , DRAGON_RANGE , allowed_dragon ) ;
# else
cango = path_exists ( r , r2 , FLY | DRAGON_LIMIT ) ;
# endif
}
if ( ! cango ) {
printf ( " L<EFBFBD> sche Ziel von %s \n " , unitname ( u ) ) ;
a_remove ( & u - > attribs , a ) ;
}
}
}
}
}
static void
fix_score_option ( void )
{
faction * f ;
for ( f = factions ; f ; f = f - > next ) {
f - > options & = ( ( 1 < < O_SCORE ) - 1 ) ;
f - > options & = ~ ( 1 < < O_MERIAN ) ;
f - > options | = ( 1 < < O_SCORE ) ;
}
}
# endif
#if 0
static void
fix_wounds ( void )
{
region * r ;
unit * u ;
for ( r = regions ; r ; r = r - > next ) {
for ( u = r - > units ; u ; u = u - > next ) {
int wounds = unit_max_hp ( u ) * u - > number - u - > hp ;
u - > hp = max ( 1 , u - > hp - wounds ) ;
}
}
}
# endif
#if 0
static void
fix_beached ( void )
{
region * r ;
for ( r = regions ; r ; r = r - > next ) {
if ( r - > land & & rterrain ( r ) ! = T_PLAIN ) {
ship * s ;
building * b ;
for ( b = r - > buildings ; b ; b = b - > next ) {
if ( b - > typ = = BT_HAFEN ) break ;
}
if ( b = = NULL ) {
for ( s = r - > ships ; s ; s = s - > next ) {
if ( s - > coast ! = NODIRECTION & & s - > type > SH_BOAT )
{
region * r2 = rconnect ( r , s - > coast ) ;
assert ( rterrain ( r2 ) = = T_OCEAN | | fval ( r2 , RF_CHAOTIC ) ) ;
move_ship ( s , r , r2 , NULL ) ;
}
}
}
}
}
}
# endif
#if 0
static void
fix_hungrydead ( void )
{
region * r ;
unit * u ;
for ( r = regions ; r ; r = r - > next ) {
for ( u = r - > units ; u ; u = u - > next ) {
if ( u - > hp = = 0 ) u - > hp = 1 ;
}
}
}
static void
name_seaserpents ( void )
{
region * r ;
unit * u ;
for ( r = regions ; r ; r = r - > next ) {
for ( u = r - > units ; u ; u = u - > next ) {
2001-12-10 01:13:39 +01:00
if ( u - > race = = new_race [ RC_SEASERPENT ] & & strncmp ( u - > name , " Nummer " , 7 ) ) {
2001-01-25 10:37:55 +01:00
set_string ( & u - > name , " Seeschlange " ) ;
}
}
}
}
2002-01-21 02:20:45 +01:00
# endif
2001-01-25 10:37:55 +01:00
static int
old_rroad ( region * r )
{
attrib * a = a_find ( r - > attribs , & at_road ) ;
if ( ! a ) return 0 ;
return a - > data . i ;
}
attrib_type at_roadfix = {
" roadfix " ,
DEFAULT_INIT ,
DEFAULT_FINALIZE ,
DEFAULT_AGE ,
# if RELEASE_VERSION<DISABLE_ROADFIX
DEFAULT_WRITE ,
# else
NULL , /* disable writing them so they will disappear */
# endif
DEFAULT_READ ,
ATF_UNIQUE
} ;
static void
newroads ( void )
{
region * r ;
for ( r = regions ; r ; r = r - > next ) if ( terrain [ rterrain ( r ) ] . roadreq > 0 ) {
direction_t d ;
int connections = 0 ;
int maxcon = MAXDIRECTIONS ;
int stones = old_rroad ( r ) ;
if ( stones < = 0 ) continue ;
for ( d = 0 ; d ! = MAXDIRECTIONS ; + + d ) {
region * r2 = rconnect ( r , d ) ;
if ( r2 & & old_rroad ( r2 ) ) + + connections ;
else if ( terrain [ rterrain ( r2 ) ] . roadreq < = 0 ) - - maxcon ;
}
if ( ! connections ) connections = maxcon ;
else maxcon = 0 ;
for ( d = 0 ; d ! = MAXDIRECTIONS & & connections ; + + d ) {
region * r2 = rconnect ( r , d ) ;
int use = stones / connections ;
if ( ! r2 | |
terrain [ rterrain ( r2 ) ] . roadreq < = 0 | |
( old_rroad ( r2 ) < = 0 & & ! maxcon ) )
continue ;
if ( use > terrain [ rterrain ( r ) ] . roadreq ) {
/* wenn etwas <20> brig bleibt (connections==1) kriegt es der regionserste */
int give = use - terrain [ rterrain ( r ) ] . roadreq ;
unit * u = r - > units ;
use = terrain [ rterrain ( r ) ] . roadreq ;
if ( u ) change_item ( u , I_STONE , give ) ;
}
rsetroad ( r , d , use ) ;
stones = stones - use ;
- - connections ;
if ( old_rroad ( r ) = = terrain [ rterrain ( r ) ] . roadreq * 2 & & old_rroad ( r2 ) = = terrain [ rterrain ( r2 ) ] . roadreq * 2 ) {
border * b = get_borders ( r , r2 ) ;
attrib * a = a_find ( b - > attribs , & at_roadfix ) ;
if ( a ) continue ;
while ( b & & b - > type ! = & bt_road ) b = b - > next ;
assert ( b ) ;
a = a_add ( & b - > attribs , a_new ( & at_roadfix ) ) ;
}
}
}
}
/* ************************************************************ */
/* GANZ WICHTIG! ALLE GE<47> NDERTEN SPR<50> CHE NEU ANZEIGEN */
/* GANZ WICHTIG! F<> GT AUCH NEUE ZAUBER IN DIE LISTE DER BEKANNTEN EIN */
/* ************************************************************ */
static void
show_newspells ( void )
{
region * r ;
2001-01-31 14:03:20 +01:00
/* Alle ge<67> nderten Zauber in das array newspellids[]. mit SPL_NOSPELL
* terminieren */
2001-09-05 21:40:40 +02:00
spellid_t newspellids [ ] = {
2002-04-21 19:47:18 +02:00
SPL_IRONKEEPER ,
2002-04-21 13:23:58 +02:00
SPL_BLOODSACRIFICE ,
2002-04-27 22:09:44 +02:00
SPL_TYBIED_DESTROY_MAGIC ,
SPL_DESTROY_MAGIC ,
2001-09-05 21:40:40 +02:00
SPL_NOSPELL } ;
2001-01-25 10:37:55 +01:00
/* die id's der neuen oder ver<65> nderten Spr<70> che werden in newspellids[]
* abgelegt */
for ( r = regions ; r ; r = r - > next ) {
unit * u ;
for ( u = r - > units ; u ; u = u - > next ) {
sc_mage * m = get_mage ( u ) ;
if ( u - > faction - > no = = MONSTER_FACTION ) continue ;
if ( m ! = NULL ) {
int i ;
if ( m - > magietyp = = M_GRAU ) continue ;
for ( i = 0 ; newspellids [ i ] ! = SPL_NOSPELL ; i + + ) {
spell * sp = find_spellbyid ( newspellids [ i ] ) ;
if ( ! sp ) continue ;
if ( m - > magietyp = = sp - > magietyp | | getspell ( u , sp - > id ) ) {
attrib * a = a_find ( u - > faction - > attribs , & at_reportspell ) ;
while ( a & & a - > data . i ! = sp - > id ) a = a - > nexttype ;
if ( ! a ) {
/* spell is not being shown yet. if seen before, remove to show again */
a = a_find ( u - > faction - > attribs , & at_seenspell ) ;
while ( a & & a - > data . i ! = sp - > id ) a = a - > nexttype ;
if ( a ) a_remove ( & u - > faction - > attribs , a ) ;
}
}
}
}
}
}
}
2002-01-21 02:20:45 +01:00
#if 0
2001-01-25 10:37:55 +01:00
static void
fix_feuerwand_orks ( void )
{
unit * u ;
if ( ( u = findunitg ( atoi36 ( " 1j1L " ) , NULL ) ) = = NULL ) {
printf ( " Korrektur: kann Orks nicht finden! \n " ) ;
return ;
}
if ( u - > number < 1000 ) {
printf ( " Korrektur: Orks sind schon korrigiert! \n " ) ;
return ;
}
scale_number ( u , 170 ) ;
u - > hp = 2337 ; /* Buggy Anzahl Personen = Normale HP */
}
static void
fix_buildings ( void )
{
building * burg ;
unit * u , * uf = NULL ;
const requirement * req ;
const construction * con ;
FILE * statfile ;
vset done ;
int s1 , s2 ;
char buf [ 256 ] ;
int a , b , c , d ;
int first ;
if ( ( statfile = fopen ( " building.txt " , " r " ) ) = = NULL ) {
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
log_warning ( ( " fix_buildings: cannot open building.txt! \n " ) ) ;
2001-01-25 10:37:55 +01:00
return ;
}
vset_init ( & done ) ;
s1 = s2 = - 1 ;
while ( fgets ( buf , 256 , statfile ) ! = NULL ) {
if ( * buf = = ' # ' )
continue ;
a = b = c = d = 0 ;
first = 0 ;
sscanf ( buf , " %d;%d;%d;%d " , & a , & b , & c , & d ) ;
if ( ( u = findunitg ( b , NULL ) ) = = NULL ) {
printf ( " fix_buildings: Einheit %d nicht gefunden. \n " , b ) ;
continue ;
}
if ( ( burg = findbuilding ( a ) ) = = NULL ) {
printf ( " fix_buildings: Burg %d nicht gefunden. \n " , a ) ;
if ( ( burg = u - > building ) = = NULL ) {
printf ( " Einheit %d steht auch in keinem Geb<65> ude. (gebe auf) \n " , u - > no ) ;
continue ;
}
if ( burg - > type - > construction - > maxsize > 0 & &
burg - > type - > construction - > reqsize > 0 )
printf ( " Ersatz: Burg %d \n " , burg - > no ) ;
else {
printf ( " Ersatzgeb<EFBFBD> ude ist nicht vom betroffenen Typ. \n " ) ;
continue ;
}
}
printf ( " Burg %d; Einheit %d; vorher %d; + %d \n " , burg - > no , u - > no , c , d ) ;
s2 = vset_add ( & done , ( void * ) a ) ;
if ( s2 > s1 ) {
printf ( " ERSTER ! \n " ) ;
first = 1 ;
uf = u ;
}
s1 = s2 ;
con = burg - > type - > construction ;
if ( con - > maxsize ! = - 1 | | con - > reqsize = = 1 ) continue ;
for ( req = con - > materials ; req - > number ! = 0 ; req + + ) {
int diff = burg - > size - c ;
if ( req - > type = = R_SILVER )
change_resource ( uf , R_SILVER , diff * req - > number - d * req - > number / con - > reqsize ) ;
else {
if ( first )
change_resource ( uf , req - > type , diff * req - > number ) ;
assert ( uf ! = NULL ) ;
change_resource ( uf , req - > type , - d * req - > number / con - > reqsize ) ;
}
}
if ( first )
burg - > size = c + d ;
else
burg - > size + = d ;
}
vset_destroy ( & done ) ;
fclose ( statfile ) ;
}
2002-01-21 02:20:45 +01:00
# endif
2001-01-25 10:37:55 +01:00
extern plane * arena ;
static void
fix_age ( void )
{
faction * f ;
2002-03-24 13:43:12 +01:00
const race * oldorc = rc_find ( " orc " ) ;
const race * uruk = rc_find ( " uruk " ) ;
2001-01-25 10:37:55 +01:00
for ( f = factions ; f ; f = f - > next ) {
2001-12-10 01:13:39 +01:00
if ( f - > no ! = MONSTER_FACTION & & playerrace ( f - > race ) ) continue ;
2002-03-24 13:43:12 +01:00
if ( f - > race = = oldorc ) f - > race = uruk ;
else if ( f - > age ! = turn ) {
2001-04-14 14:11:45 +02:00
log_printf ( " Alter von Partei %s auf %d angepasst. \n " , factionid ( f ) , turn ) ;
2001-01-25 10:37:55 +01:00
f - > age = turn ;
}
}
}
#if 0
static boolean
balsambug ( const region * r )
{
direction_t dir ;
for ( dir = 0 ; dir < MAXDIRECTIONS ; dir + + ) {
if ( landregion ( rterrain ( rconnect ( r , dir ) ) ) & & rdemand ( r , 0 ) > 0 )
return false ;
}
return true ;
}
static void
fix_balsamfiasko ( void )
{
region * r , * rc ;
direction_t dir ;
int i ;
for ( r = regions ; r ; r = r - > next ) freset ( r , RF_DH ) ;
/* Zuf<75> llig verteilen */
for ( r = regions ; r ; r = r - > next ) {
if ( r - > x < - 36 & & r - > y < - 45 & & landregion ( rterrain ( r ) ) ) {
if ( rdemand ( r , 0 ) < = 0 & & balsambug ( r ) ) {
rsetdemand ( r , 0 , ( char ) ( 1 + rand ( ) % 5 ) ) ;
rsetdemand ( r , rand ( ) % 7 , 0 ) ;
fset ( r , RF_DH ) ;
}
}
}
/* Smoothing */
for ( i = 0 ; i < 3 ; i + + ) {
for ( r = regions ; r ; r = r - > next ) if ( fval ( r , RF_DH ) ) {
for ( dir = 0 ; dir < MAXDIRECTIONS ; dir + + ) {
rc = rconnect ( r , dir ) ;
if ( rc & & fval ( rc , RF_DH ) & & rand ( ) % 100 < 20 ) {
int p1 , p2 ;
for ( p1 = 0 ; p1 ! = MAXLUXURIES ; p1 + + )
if ( rdemand ( r , p1 ) = = 0 ) break ;
for ( p2 = 0 ; p2 ! = MAXLUXURIES ; p2 + + )
if ( rdemand ( rc , p2 ) = = 0 ) break ;
if ( p1 ! = p2 ) {
rsetdemand ( rc , p2 , ( char ) ( 1 + rand ( ) % 5 ) ) ;
rsetdemand ( rc , p1 , 0 ) ;
}
}
}
}
}
}
# endif
2001-12-10 01:13:39 +01:00
# if 1
2001-02-10 14:20:09 +01:00
static int
2001-02-03 14:45:35 +01:00
count_demand ( const region * r )
{
struct demand * dmd ;
int c = 0 ;
2001-02-10 20:24:05 +01:00
if ( r - > land ) {
for ( dmd = r - > land - > demands ; dmd ; dmd = dmd - > next ) c + + ;
}
2001-02-03 14:45:35 +01:00
return c ;
}
2001-02-20 23:54:05 +01:00
# endif
2001-02-03 14:45:35 +01:00
2001-02-10 20:24:05 +01:00
static int
recurse_regions ( region * r , regionlist * * rlist , boolean ( * fun ) ( const region * r ) )
2001-02-03 14:45:35 +01:00
{
2001-02-10 20:24:05 +01:00
if ( ! fun ( r ) ) return 0 ;
else {
int len = 0 ;
direction_t d ;
regionlist * rl = calloc ( sizeof ( regionlist ) , 1 ) ;
rl - > next = * rlist ;
rl - > region = r ;
( * rlist ) = rl ;
fset ( r , FL_MARK ) ;
for ( d = 0 ; d ! = MAXDIRECTIONS ; + + d ) {
region * nr = rconnect ( r , d ) ;
if ( nr & & ! fval ( nr , FL_MARK ) ) len + = recurse_regions ( nr , rlist , fun ) ;
}
return len + 1 ;
}
}
2001-02-03 14:45:35 +01:00
2001-12-10 01:13:39 +01:00
# if 1
2001-09-05 21:40:40 +02:00
static int maxluxuries = 0 ;
2001-02-10 20:24:05 +01:00
static boolean
f_nolux ( const region * r )
{
if ( r - > land & & count_demand ( r ) ! = maxluxuries ) return true ;
return false ;
}
2001-02-03 14:45:35 +01:00
2001-12-10 01:13:39 +01:00
static int
2001-02-10 20:24:05 +01:00
fix_demand_region ( region * r )
{
regionlist * rl , * rlist = NULL ;
static const luxury_type * * mlux = 0 , * * ltypes ;
const luxury_type * sale = NULL ;
int maxlux = 0 ;
recurse_regions ( r , & rlist , f_nolux ) ;
if ( mlux = = 0 ) {
int i = 0 ;
if ( maxluxuries = = 0 ) for ( sale = luxurytypes ; sale ; sale = sale - > next ) {
maxluxuries + + ;
}
mlux = ( const luxury_type * * ) gc_add ( calloc ( maxluxuries , sizeof ( const luxury_type * ) ) ) ;
ltypes = ( const luxury_type * * ) gc_add ( calloc ( maxluxuries , sizeof ( const luxury_type * ) ) ) ;
for ( sale = luxurytypes ; sale ; sale = sale - > next ) {
ltypes [ i + + ] = sale ;
}
}
else {
int i ;
for ( i = 0 ; i ! = maxluxuries ; + + i ) mlux [ i ] = 0 ;
}
for ( rl = rlist ; rl ; rl = rl - > next ) {
region * r = rl - > region ;
direction_t d ;
for ( d = 0 ; d ! = MAXDIRECTIONS ; + + d ) {
region * nr = rconnect ( r , d ) ;
if ( nr & & nr - > land & & nr - > land - > demands ) {
struct demand * dmd ;
for ( dmd = nr - > land - > demands ; dmd ; dmd = dmd - > next ) {
if ( dmd - > value = = 0 ) {
int i ;
for ( i = 0 ; i ! = maxluxuries ; + + i ) {
if ( mlux [ i ] = = NULL ) {
maxlux = i ;
mlux [ i ] = dmd - > type ;
break ;
} else if ( mlux [ i ] = = dmd - > type ) {
break ;
}
}
break ;
}
2001-02-03 14:45:35 +01:00
}
}
}
2001-02-10 20:24:05 +01:00
freset ( r , FL_MARK ) ; /* undo recursive marker */
}
if ( maxlux < 2 ) {
int i ;
for ( i = maxlux ; i ! = 2 ; + + i ) {
int j ;
do {
int k = rand ( ) % maxluxuries ;
mlux [ i ] = ltypes [ k ] ;
for ( j = 0 ; j ! = i ; + + j ) {
if ( mlux [ j ] = = mlux [ i ] ) break ;
}
} while ( j ! = i ) ;
}
maxlux = 2 ;
}
for ( rl = rlist ; rl ; rl = rl - > next ) {
region * r = rl - > region ;
2002-02-06 09:06:02 +01:00
log_warning ( ( " fixing demand in %s \n " , regionname ( r , NULL ) ) ) ;
2001-02-10 20:24:05 +01:00
setluxuries ( r , mlux [ rand ( ) % maxlux ] ) ;
}
while ( rlist ) {
rl = rlist - > next ;
free ( rlist ) ;
rlist = rl ;
}
2001-12-10 01:13:39 +01:00
return 0 ;
2001-02-10 20:24:05 +01:00
}
2001-02-20 23:54:05 +01:00
# endif
2001-02-10 20:24:05 +01:00
2001-09-05 21:40:40 +02:00
static void
fix_firewalls ( void )
{
region * r = regions ;
while ( r ) {
direction_t d ;
for ( d = 0 ; d ! = MAXDIRECTIONS ; + + d ) {
region * r2 = rconnect ( r , d ) ;
if ( r2 ) {
border * b = get_borders ( r , r2 ) ;
while ( b ) {
if ( b - > type = = & bt_firewall ) {
attrib * a = a_find ( b - > attribs , & at_countdown ) ;
if ( a = = NULL | | a - > data . i < = 0 ) {
erase_border ( b ) ;
log_warning ( ( " firewall between regions %s and %s was bugged. removed. \n " ,
regionid ( r ) , regionid ( r2 ) ) ) ;
b = get_borders ( r , r2 ) ;
} else {
b = b - > next ;
}
} else {
b = b - > next ;
}
}
}
}
r = r - > next ;
}
}
2001-02-10 20:24:05 +01:00
extern attrib * make_atgmcreate ( const struct item_type * itype ) ;
extern attrib * make_atpermissions ( void ) ;
extern struct attrib_type at_permissions ;
2001-09-05 21:40:40 +02:00
extern struct attrib_type at_gmcreate ;
2001-02-10 20:24:05 +01:00
static void
2001-05-11 22:19:22 +02:00
update_gms ( void )
2001-02-10 20:24:05 +01:00
{
2001-05-11 22:19:22 +02:00
faction * f ;
for ( f = factions ; f ; f = f - > next ) {
2001-09-05 21:40:40 +02:00
attrib * permissions = a_find ( f - > attribs , & at_permissions ) ;
if ( permissions ) {
2002-02-24 10:20:38 +01:00
const char * keys [ ] = { " gmgate " , " gmmsgr " , " gmkill " , " gmmsgu " , NULL } ;
2002-01-28 02:55:31 +01:00
int k ;
2001-09-05 21:40:40 +02:00
item_t i ;
2002-01-28 02:55:31 +01:00
for ( k = 0 ; keys [ k ] ; + + k ) {
2002-03-02 20:26:39 +01:00
add_key ( ( attrib * * ) & permissions - > data . v , atoi36 ( keys [ k ] ) ) ;
2001-09-05 21:40:40 +02:00
}
2002-01-28 02:55:31 +01:00
for ( i = I_GREATSWORD ; i ! = I_KEKS ; + + i ) {
attrib * a = a_find ( permissions , & at_gmcreate ) ;
while ( a & & a - > data . v ! = ( void * ) olditemtype [ i ] ) a = a - > nexttype ;
if ( ! a ) a_add ( ( attrib * * ) & permissions - > data . v , make_atgmcreate ( olditemtype [ i ] ) ) ;
2001-09-05 21:40:40 +02:00
}
2002-01-28 02:55:31 +01:00
}
}
}
static int
fix_gms ( void )
{
faction * f ;
for ( f = factions ; f ; f = f - > next ) {
attrib * permissions = a_find ( f - > attribs , & at_permissions ) ;
if ( permissions ) {
const char * keys [ ] = { " gmgate " , " gmmsgr " , " gmmsgr " , " gmmsgu " , NULL } ;
int k ;
item_t i ;
for ( k = 0 ; keys [ k ] ; + + k ) {
attrib * a = find_key ( ( attrib * ) permissions - > data . v , atoi36 ( " gmgate " ) ) ;
if ( a ) {
attrib * * ap = & a - > nexttype ;
while ( * ap ) {
attrib * an = * ap ;
if ( a - > data . i = = an - > data . i ) a_remove ( ap , an ) ;
else ap = & an - > next ;
}
}
2001-12-10 01:13:39 +01:00
}
2001-09-05 21:40:40 +02:00
for ( i = I_GREATSWORD ; i ! = I_KEKS ; + + i ) {
attrib * a = a_find ( permissions , & at_gmcreate ) ;
while ( a & & a - > data . v ! = ( void * ) olditemtype [ i ] ) a = a - > nexttype ;
2002-01-28 02:55:31 +01:00
if ( a ) {
attrib * * ap = & a - > nexttype ;
while ( * ap ) {
attrib * an = * ap ;
if ( a - > data . v = = an - > data . v ) a_remove ( ap , an ) ;
else ap = & an - > next ;
}
}
2001-02-10 20:24:05 +01:00
}
}
2001-02-03 14:45:35 +01:00
}
2002-01-28 02:55:31 +01:00
return 0 ;
2001-02-03 14:45:35 +01:00
}
2001-12-10 01:13:39 +01:00
# if 1
static int
2001-02-03 14:45:35 +01:00
fix_demand ( void )
{
region * r ;
2001-02-10 20:24:05 +01:00
const luxury_type * sale = NULL ;
if ( maxluxuries = = 0 ) for ( sale = luxurytypes ; sale ; sale = sale - > next ) + + maxluxuries ;
2001-02-03 14:45:35 +01:00
2001-02-10 20:24:05 +01:00
for ( r = regions ; r ; r = r - > next ) {
if ( ( r - > land ) & & count_demand ( r ) ! = maxluxuries ) {
fix_demand_region ( r ) ;
}
2001-02-03 14:45:35 +01:00
}
2001-12-10 01:13:39 +01:00
return 0 ;
2001-02-03 14:45:35 +01:00
}
2001-02-20 23:54:05 +01:00
# endif
2001-02-03 14:45:35 +01:00
2001-01-25 10:37:55 +01:00
#if 0
static void
read_laenrepair ( boolean active )
{
FILE * f = fopen ( " repair.laen " , " rt " ) ;
FILE * log = fopen ( " report.laen " , " wt " ) ;
if ( ! f | | ! log ) return ;
while ( ! feof ( f ) ) {
int n , x , y ;
region * r ;
fscanf ( f , " %d %d %d " , & x , & y , & n ) ;
r = findregion ( x , y ) ;
if ( ! r ) fprintf ( log , " %d,%d: \t not found \n " , x , y ) ;
else if ( fval ( r , RF_CHAOTIC ) ) continue ;
else {
int laen = rlaen ( r ) ;
if ( n = = - 1 & & laen > = 0 ) {
fprintf ( log , " %d,%d: \t illegal laen (%d) \n " , x , y , laen ) ;
if ( active ) rsetlaen ( r , n ) ;
} else if ( laen = = - 1 & & n ! = - 1 ) {
fprintf ( log , " %d,%d: \t laen was lost (%d) \n " , x , y , n ) ;
if ( active ) rsetlaen ( r , n ) ;
}
}
}
fclose ( f ) ;
}
static void
write_laenrepair ( void ) {
FILE * f = fopen ( " repair.laen " , " wt " ) ;
region * r ;
for ( r = regions ; r ; r = r - > next ) if ( ! fval ( r , RF_CHAOTIC ) ) {
int laen = rlaen ( r ) ;
fprintf ( f , " %d %d %d \n " , r - > x , r - > y , laen ) ;
}
fclose ( f ) ;
}
# endif
# include "group.h"
static void
fix_allies ( void ) {
faction * f ;
for ( f = factions ; f ; f = f - > next ) {
group * g ;
for ( g = f - > groups ; g ; g = g - > next ) {
ally * * ap = & g - > allies ;
while ( * ap ) {
ally * an , * a = * ap ;
for ( an = a - > next ; an ; an = an - > next ) {
if ( a - > faction = = an - > faction ) {
* ap = a - > next ;
free ( a ) ;
break ;
}
}
if ( an = = NULL ) ap = & ( * ap ) - > next ;
}
}
}
}
# ifdef FUZZY_BASE36
extern boolean enable_fuzzy ;
# endif
2001-02-10 14:20:09 +01:00
static void
2001-01-25 10:37:55 +01:00
fix_icastles ( void )
{
region * r ;
for ( r = regions ; r ; r = r - > next ) {
building * b ;
for ( b = r - > buildings ; b ; b = b - > next ) {
attrib * a ;
2002-03-27 22:49:27 +01:00
const building_type * btype = bt_find ( " castle " ) ;
2001-01-25 10:37:55 +01:00
icastle_data * data ;
a = a_find ( b - > attribs , & at_icastle ) ;
2002-03-27 22:49:27 +01:00
if ( b - > type ! = bt_find ( " illusion " ) & & ! a ) continue ;
2001-01-25 10:37:55 +01:00
if ( ! a ) {
/* attribut hat gefehle */
a = a_add ( & b - > attribs , a_new ( & at_icastle ) ) ;
}
2002-03-27 22:49:27 +01:00
if ( b - > type ! = bt_find ( " illusion " ) ) {
2001-01-25 10:37:55 +01:00
/* geb<65> udetyp war falsch */
btype = b - > type ;
2002-03-27 22:49:27 +01:00
b - > type = bt_find ( " illusion " ) ;
2001-01-25 10:37:55 +01:00
}
data = ( icastle_data * ) a - > data . v ;
if ( data - > time < = 0 ) {
/* zeit war kaputt oder abgelaufen */
data - > time = 1 ;
}
if ( ! data - > type ) {
/* typ muss gesetzt werden, weil er nicht geladen wurde */
data - > type = btype ;
}
if ( data - > building ! = b ) {
/* r<> ckw<6B> rtszeiger auf das geb<65> ude reparieren */
data - > building = b ;
}
}
}
}
#if 0
static void
fix_ponnukis ( void )
/* Es kann nur einen geben! */
{
unit * ponn = findunit ( atoi36 ( " ponn " ) ) ;
if ( ponn ) {
region * mag = ponn - > region ;
unit * u ;
for ( u = mag - > units ; u ; u = u - > next ) {
if ( u ! = ponn & & u - > faction = = ponn - > faction & & u - > race = = ponn - > race & & ! strcmp ( ponn - > name , u - > name ) ) {
set_number ( u , 0 ) ;
}
}
}
}
# endif
#if 0
static void
fix_traveldir ( void )
{
region * r ;
attrib * a , * a2 ;
traveldir * t ;
for ( r = regions ; r ; r = r - > next ) {
a = a_find ( r - > attribs , & at_traveldir ) ;
while ( a ) {
a2 = a_add ( & r - > attribs , a_new ( & at_traveldir_new ) ) ;
t = ( traveldir * ) ( a2 - > data . v ) ;
t - > no = a - > data . sa [ 0 ] ;
t - > dir = a - > data . ca [ 2 ] ;
t - > age = a - > data . ca [ 3 ] ;
a = a - > nexttype ;
}
}
for ( r = regions ; r ; r = r - > next ) {
a = a_find ( r - > attribs , & at_traveldir ) ;
while ( a ) {
a_remove ( & r - > attribs , a ) ;
a = a - > nexttype ;
}
}
}
# endif
static void
stats ( void )
{
FILE * F ;
item * items = NULL ;
2001-02-03 14:45:35 +01:00
char zText [ MAX_PATH ] ;
2001-01-25 10:37:55 +01:00
2001-02-03 14:45:35 +01:00
strcat ( strcpy ( zText , resourcepath ( ) ) , " /stats " ) ;
F = fopen ( zText , " wt " ) ;
2001-01-25 10:37:55 +01:00
if ( F ) {
region * r ;
const item_type * itype ;
for ( r = regions ; r ; r = r - > next ) {
unit * u ;
item * itm ;
for ( u = r - > units ; u ; u = u - > next ) {
for ( itm = u - > items ; itm ; itm = itm - > next ) {
2002-03-11 01:06:14 +01:00
if ( itm - > number > 10000000 ) {
itm - > number = 1 ;
}
2001-01-25 10:37:55 +01:00
i_change ( & items , itm - > type , itm - > number ) ;
}
}
}
for ( itype = itemtypes ; itype ; itype = itype - > next ) {
item * itm = * i_find ( & items , itype ) ;
if ( itm & & itm - > number )
fprintf ( F , " %4d %s \n " , itm - > number , locale_string ( NULL , resourcename ( itype - > rtype , 0 ) ) ) ;
else
fprintf ( F , " %4d %s \n " , 0 , locale_string ( NULL , resourcename ( itype - > rtype , 0 ) ) ) ;
}
fclose ( F ) ;
} else {
2001-02-03 14:45:35 +01:00
perror ( zText ) ;
2001-01-25 10:37:55 +01:00
}
}
2002-01-21 02:20:45 +01:00
#if 0
2001-01-25 10:37:55 +01:00
static void
fix_prices ( void )
{
region * r ;
puts ( " - Korrigiere Handelsg<73> terpreise " ) ;
2001-04-08 19:36:50 +02:00
for ( r = regions ; r ; r = r - > next ) if ( r - > land ) {
int sales = 0 , buys = 0 ;
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
const luxury_type * sale = NULL , * ltype ;
2001-04-08 19:36:50 +02:00
struct demand * dmd ;
for ( dmd = r - > land - > demands ; dmd ; dmd = dmd - > next ) {
if ( dmd - > value = = 0 ) {
sales + + ;
sale = dmd - > type ;
} else {
buys + + ;
}
}
if ( sales = = 0 ) {
int c = 0 ;
for ( ltype = luxurytypes ; ltype ; ltype = ltype - > next ) c + + ;
c = rand ( ) % c ;
for ( ltype = luxurytypes ; c > 0 ; c - - ) ltype = ltype - > next ;
r_setdemand ( r , ltype , 0 ) ;
sale = ltype ;
}
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
assert ( sale ) ;
2001-04-08 19:36:50 +02:00
if ( buys = = 0 ) {
for ( ltype = luxurytypes ; ltype ; ltype = ltype - > next ) {
if ( ltype ! = sale ) r_setdemand ( r , ltype , 1 + rand ( ) % 5 ) ;
2001-01-25 10:37:55 +01:00
}
}
}
}
static void
fix_options ( void )
{
faction * f ;
puts ( " - Korrigiere Parteioptionen " ) ;
for ( f = factions ; f ; f = f - > next ) {
f - > options = f - > options | Pow ( O_REPORT ) ;
f - > options = f - > options | Pow ( O_ZUGVORLAGE ) ;
}
}
static void
init_region_age ( void )
{
region * r ;
puts ( " - Initialisiere r->age " ) ;
/* Initialisieren mit dem Alter der <20> ltesten Partei in 2 Feldern
* Umkreis */
for ( r = regions ; r ; r = r - > next ) {
regionlist * rl = all_in_range ( r , 2 ) ;
regionlist * rl2 ;
unit * u ;
int maxage = 0 ;
for ( rl2 = rl ; rl2 ; rl2 = rl2 - > next ) {
for ( u = rl2 - > region - > units ; u ; u = u - > next ) {
if ( u - > faction - > age > maxage ) maxage = u - > faction - > age ;
}
}
r - > age = ( unsigned short ) maxage ;
}
}
static void
fix_herbtypes ( void )
{
region * r ;
for ( r = regions ; r ! = NULL ; r = r - > next ) if ( r - > land ) {
const herb_type * htype = r - > land - > herbtype ;
if ( htype = = NULL ) {
if ( terrain [ r - > terrain ] . herbs ! = NULL ) {
const item_type * itype ;
int i = 0 ;
while ( terrain [ r - > terrain ] . herbs [ i ] ! = NULL ) + + i ;
itype = finditemtype ( terrain [ r - > terrain ] . herbs [ rand ( ) % i ] , NULL ) ;
r - > land - > herbtype = resource2herb ( itype - > rtype ) ;
}
} else {
if ( r - > terrain = = T_PLAIN ) {
if ( r_isforest ( r ) ) {
int i = rand ( ) % 3 + 3 ;
const char * name = terrain [ T_PLAIN ] . herbs [ i ] ;
const item_type * itype = finditemtype ( name , NULL ) ;
r - > land - > herbtype = resource2herb ( itype - > rtype ) ;
}
} else {
/* Das geht so nicht, wegen der Eisberg-Terrains */
/* assert(htype->terrain==r->terrain); */
}
}
}
}
# endif
2002-04-03 01:42:07 +02:00
static int
fix_plainherbs ( void )
{
2002-05-01 21:44:28 +02:00
# define WINDOWSIZE 120
# define DEVIATION 1.1
herb_t window [ WINDOWSIZE ] ;
int wbegin = 0 , wend = 0 ;
region * r ;
int c ;
2002-04-21 13:29:22 +02:00
int count [ 6 ] ;
for ( c = 0 ; c ! = 6 ; + + c ) count [ c ] = 0 ;
2002-04-03 01:42:07 +02:00
for ( r = regions ; r ; r = r - > next ) {
2002-05-01 21:44:28 +02:00
herb_t herb ;
int wnext = ( wend + 1 ) % WINDOWSIZE ;
2002-04-03 01:42:07 +02:00
const char * name ;
terrain_t t = rterrain ( r ) ;
if ( t ! = T_PLAIN ) continue ;
name = LOC ( default_locale , rherbtype ( r ) - > itype - > rtype - > _name [ 0 ] ) ;
2002-05-01 21:44:28 +02:00
for ( herb = 0 ; herb ! = 6 ; + + herb ) {
if ( strcmp ( terrain [ t ] . herbs [ herb ] , name ) = = 0 ) {
+ + count [ herb ] ;
2002-04-21 13:29:22 +02:00
break ;
}
}
2002-05-01 21:44:28 +02:00
if ( wnext = = wbegin ) {
const struct herb_type * htype = NULL ;
while ( count [ herb ] > WINDOWSIZE / 6 * DEVIATION ) {
- - count [ herb ] ;
herb = rand ( ) % 6 ;
+ + count [ herb ] ;
}
htype = resource2herb ( finditemtype ( terrain [ t ] . herbs [ herb ] , default_locale ) - > rtype ) ;
2002-04-03 01:42:07 +02:00
rsetherbtype ( r , htype ) ;
2002-05-01 21:44:28 +02:00
- - count [ window [ wbegin ] ] ;
+ + wbegin ;
2002-04-21 13:29:22 +02:00
}
2002-05-01 21:44:28 +02:00
window [ wend ] = herb ;
wend = wnext ;
r = r - > next ;
2002-04-21 13:29:22 +02:00
}
2002-05-01 21:44:28 +02:00
/* check, output: */
2002-04-21 13:29:22 +02:00
for ( c = 0 ; c ! = 6 ; + + c ) count [ c ] = 0 ;
for ( r = regions ; r ; r = r - > next ) {
int i ;
const char * name ;
terrain_t t = rterrain ( r ) ;
if ( t ! = T_PLAIN ) continue ;
name = LOC ( default_locale , rherbtype ( r ) - > itype - > rtype - > _name [ 0 ] ) ;
for ( i = 0 ; i ! = 6 ; + + i ) {
if ( strcmp ( terrain [ t ] . herbs [ i ] , name ) = = 0 ) {
count [ i ] + + ;
break ;
}
2002-04-03 01:42:07 +02:00
}
2002-04-21 13:29:22 +02:00
r = r - > next ;
2002-04-03 01:42:07 +02:00
}
2002-04-21 13:29:22 +02:00
for ( c = 0 ; c ! = 6 ; + + c ) log_warning ( ( " Herbs %d : %d \n " , c , count [ c ] ) ) ;
2002-04-03 01:42:07 +02:00
return 0 ;
}
2001-01-25 10:37:55 +01:00
# ifdef SKILLFIX_SAVE
typedef struct skillfix_data {
unit * u ;
skill_t skill ;
int value ;
int number ;
int self ;
int teach ;
} skillfix_data ;
static void
init_skillfix ( attrib * a )
{
a - > data . v = calloc ( sizeof ( skillfix_data ) , 1 ) ;
}
static void
free_skillfix ( attrib * a )
{
free ( a - > data . v ) ;
}
attrib_type at_skillfix = { " skillfix " , init_skillfix , free_skillfix } ;
2001-04-01 08:58:45 +02:00
void
2001-01-25 10:37:55 +01:00
skillfix ( struct unit * u , skill_t skill , int from , int self , int teach )
{
attrib * a = a_add ( & u - > attribs , a_new ( & at_skillfix ) ) ;
skillfix_data * data = ( skillfix_data * ) a - > data . v ;
data - > u = u ;
data - > skill = skill ;
data - > number = u - > number ;
data - > value = from ;
data - > self = self ;
data - > teach = teach ;
}
void
write_skillfix ( void )
{
FILE * F = fopen ( " skills.fix " , " w+ " ) ;
region * r ;
fprintf ( F , " S%d \n " , turn ) ;
for ( r = regions ; r ; r = r - > next ) {
unit * u ;
for ( u = r - > units ; u ; u = u - > next ) {
attrib * a = a_find ( u - > attribs , & at_skillfix ) ;
while ( a ) {
skillfix_data * data = ( skillfix_data * ) a - > data . v ;
2001-04-01 08:58:45 +02:00
fprintf ( F , " %s %d %d %d %d %d \n " ,
2001-01-25 10:37:55 +01:00
itoa36 ( data - > u - > no ) ,
data - > skill ,
data - > number ,
data - > value ,
data - > self ,
data - > teach ) ;
a = a - > nexttype ;
}
}
}
fclose ( F ) ;
}
# endif
2002-01-21 02:20:45 +01:00
#if 0
2001-01-25 10:37:55 +01:00
static void
init_mwarden ( void )
{
unit * u = findunitg ( atoi36 ( " mwar " ) , NULL ) ;
attrib * a ;
if ( ! u ) return ;
a = a_add ( & u - > attribs , a_new ( & at_warden ) ) ;
a - > data . i = 0 ;
}
2002-01-21 02:20:45 +01:00
# endif
2001-01-25 10:37:55 +01:00
# ifdef CONVERT_TRIGGER
2001-02-03 14:45:35 +01:00
# include "old/relation.h"
# include "old/trigger.h"
# include "old/trigger_internal.h"
2001-01-27 19:15:52 +01:00
2001-01-25 10:37:55 +01:00
# include <event.h>
2001-01-27 19:15:52 +01:00
2001-01-25 10:37:55 +01:00
# include <triggers/killunit.h>
# include <triggers/timeout.h>
# include <triggers/changerace.h>
# include <triggers/changefaction.h>
# include <triggers/createunit.h>
# include <triggers/giveitem.h>
# include <triggers/createcurse.h>
# include <triggers/shock.h>
typedef struct {
void * obj2 ;
typ_t typ2 ;
relation_t id ;
spread_t spread ;
} reldata ;
extern timeout * all_timeouts ;
static void
convert_triggers ( void )
{
region * r = regions ;
timeout * t ;
while ( r ) {
unit * u = r - > units ;
while ( u ) {
attrib * a = a_find ( u - > attribs , & at_relation ) ;
while ( a ) {
reldata * rel = ( reldata * ) a - > data . v ;
unit * u2 = ( unit * ) rel - > obj2 ;
switch ( rel - > id ) {
case REL_FAMILIAR :
if ( u & & u2 ) {
2001-12-10 01:13:39 +01:00
if ( ! playerrace ( u - > race ) | | ( playerrace ( u2 - > race ) & & u - > race = = RC_GOBLIN ) )
2001-01-27 20:30:07 +01:00
set_familiar ( u2 , u ) ;
2001-04-01 08:58:45 +02:00
else
2001-01-27 20:30:07 +01:00
set_familiar ( u , u2 ) ;
2001-01-25 10:37:55 +01:00
} else {
if ( u2 ) fprintf ( stderr , " WARNING: FAMILIAR info for %s may be broken! \n " , unitname ( u2 ) ) ;
if ( u ) fprintf ( stderr , " WARNING: FAMILIAR info for %s may be broken! \n " , unitname ( u ) ) ;
}
break ;
case REL_CREATOR :
break ;
case REL_TARGET :
fprintf ( stderr , " WARNING: TARGET relation between %s and 0x%p not converted \n " , unitname ( u ) , u2 ) ;
break ;
default :
fprintf ( stderr , " WARNING: unknown relation %d between %s and 0x%p not converted \n " , rel - > id , unitname ( u ) , u2 ) ;
break ;
}
2001-02-03 19:46:15 +01:00
a = a - > nexttype ;
2001-01-25 10:37:55 +01:00
}
u = u - > next ;
}
r = r - > next ;
}
for ( t = all_timeouts ; t ; t = t - > next ) {
actionlist * al = t - > acts ;
int time = t - > ticks ;
for ( ; al ; al = al - > next ) {
action * act = al - > act ;
if ( act ) switch ( act - > atype ) {
case AC_DESTROY : {
/* conversion keeper */
unit * u = ( unit * ) act - > obj ;
trigger * tkill = trigger_killunit ( u ) ;
add_trigger ( & u - > attribs , " timer " , trigger_timeout ( time , tkill ) ) ;
}
case AC_CHANGERACE : {
/* conversion for toads */
unit * u = ( unit * ) act - > obj ;
race_t race = ( race_t ) act - > i [ 0 ] ;
race_t irace = ( race_t ) act - > i [ 1 ] ;
trigger * trestore = trigger_changerace ( u , race , irace ) ;
if ( rand ( ) % 10 > 2 ) t_add ( & trestore , trigger_giveitem ( u , olditemtype [ I_TOADSLIME ] , 1 ) ) ;
add_trigger ( & u - > attribs , " timer " , trigger_timeout ( time , trestore ) ) ;
break ;
}
case AC_CHANGEIRACE : {
/* conversion for shapeshift */
unit * u = ( unit * ) act - > obj ;
race_t irace = ( race_t ) act - > i [ 0 ] ;
trigger * trestore = trigger_changerace ( u , NORACE , irace ) ;
add_trigger ( & u - > attribs , " timer " , trigger_timeout ( time , trestore ) ) ;
break ;
}
case AC_CHANGEFACTION : {
/* charmingsong */
faction * f = findfaction_unique_id ( act - > i [ 0 ] ) ;
unit * u = ( unit * ) act - > obj ;
trigger * trestore = trigger_changefaction ( u , f ) ;
add_trigger ( & u - > attribs , " timer " , trigger_timeout ( time , trestore ) ) ;
add_trigger ( & u - > faction - > attribs , " destroy " , trigger_killunit ( u ) ) ;
add_trigger ( & f - > attribs , " destroy " , trigger_killunit ( u ) ) ;
break ;
}
case AC_CREATEUNIT : {
/* conversion summon_dragon */
faction * f = findfaction_unique_id ( act - > i [ 0 ] ) ;
region * r = ( region * ) act - > obj ;
int number = act - > i [ 1 ] ;
race_t race = ( race_t ) act - > i [ 2 ] ;
trigger * tsummon = trigger_createunit ( r , f , race , number ) ;
add_trigger ( & r - > attribs , " timer " , trigger_timeout ( time , tsummon ) ) ;
break ;
}
case AC_CREATEMAGICBOOSTCURSE : {
/* delayed magic boost curse */
unit * mage = ( unit * ) act - > obj ;
trigger * tsummon = trigger_createcurse ( mage , mage , C_AURA , 0 , act - > i [ 0 ] , 6 , 50 , 1 ) ;
add_trigger ( & mage - > attribs , " timer " , trigger_timeout ( 5 , tsummon ) ) ;
break ;
}
default :
fprintf ( stderr , " WARNING: timeout not converted \n " ) ;
}
}
}
}
# endif
2001-02-20 23:54:05 +01:00
#if 0
2001-02-02 09:40:49 +01:00
# include <items/lmsreward.h>
2001-01-25 10:37:55 +01:00
static void
lms_special ( unit * u )
{
2001-02-03 14:45:35 +01:00
if ( u ) i_change ( & u - > items , & it_lmsreward , 1 ) ;
2001-02-02 09:40:49 +01:00
}
2001-02-20 23:54:05 +01:00
# endif
2001-02-02 09:40:49 +01:00
2001-02-20 23:54:05 +01:00
#if 0
2001-02-02 09:40:49 +01:00
# define LIFEEXPECTANCY (27*40)
static void
undo_deadpeasants ( void )
{
region * r = regions ;
while ( r ) {
int dead = rpeasants ( r ) / LIFEEXPECTANCY ;
deathcounts ( r , - dead ) ;
r = r - > next ;
}
2001-01-25 10:37:55 +01:00
}
2001-05-20 23:47:56 +02:00
static void
fix_undead3percent ( void )
{
region * r = regions ;
while ( r ) {
int dead = deathcount ( r ) ;
deathcounts ( r , - ( dead / 2 ) ) ;
r = r - > next ;
}
}
2001-02-25 20:31:40 +01:00
static void
2001-02-04 12:18:27 +01:00
fix_targetregion_resolve ( void )
{
region * r ;
unit * u ;
attrib * a ;
for ( r = regions ; r ; r = r - > next ) {
for ( u = r - > units ; u ; u = u - > next ) {
a = a_find ( u - > attribs , & at_targetregion ) ;
if ( a ) a - > data . v = findregion ( a - > data . sa [ 0 ] , a - > data . sa [ 1 ] ) ;
}
}
}
2001-02-25 20:31:40 +01:00
static void
fix_herbs ( void )
2001-02-09 20:52:59 +01:00
{
2001-02-25 20:31:40 +01:00
const char * plain_herbs [ ] = { " Flachwurz " , " W<EFBFBD> rziger Wagemut " , " Eulenauge " , " Gr<EFBFBD> ner Spinnerich " , " Blauer Baumringel " , " Elfenlieb " } ;
const herb_type * htypes [ 6 ] ;
int herbs [ 6 ] ;
int hneed [ 6 ] ;
2001-02-09 20:52:59 +01:00
region * r ;
2001-02-25 20:31:40 +01:00
int i , hsum = 0 , left = 0 ;
for ( i = 0 ; i ! = 6 ; + + i ) {
htypes [ i ] = resource2herb ( finditemtype ( plain_herbs [ i ] , NULL ) - > rtype ) ;
herbs [ i ] = 0 ;
}
for ( r = regions ; r ; r = r - > next ) if ( rterrain ( r ) = = T_PLAIN ) {
const herb_type * htype = rherbtype ( r ) ;
2001-04-14 14:11:45 +02:00
if ( htype = = NULL ) {
htype = htypes [ i ] ;
rsetherbtype ( r , htype ) ;
}
2001-02-25 20:31:40 +01:00
for ( i = 0 ; i ! = 6 ; + + i ) if ( htypes [ i ] = = htype ) break ;
assert ( i ! = 6 ) ;
herbs [ i ] + + ;
hsum + + ;
}
for ( i = 0 ; i ! = 6 ; + + i ) {
int hwant = hsum / ( 6 - i ) ;
hneed [ i ] = hwant - herbs [ i ] ;
if ( hneed [ i ] > 0 ) left + = hneed [ i ] ;
hsum - = hwant ;
}
for ( r = regions ; r ; r = r - > next ) if ( rterrain ( r ) = = T_PLAIN ) {
const herb_type * htype = rherbtype ( r ) ;
assert ( htype ) ;
for ( i = 0 ; i ! = 6 ; + + i ) if ( htypes [ i ] = = htype ) break ;
assert ( i ! = 6 ) ;
if ( hneed [ i ] < 0 ) {
int p ;
int k = rand ( ) % left ;
for ( p = 0 ; p ! = 6 ; + + p ) if ( hneed [ p ] > 0 ) {
k - = hneed [ p ] ;
if ( k < 0 ) break ;
}
assert ( p ! = 6 ) ;
hneed [ p ] - - ;
hneed [ i ] + + ;
left - - ;
rsetherbtype ( r , htypes [ p ] ) ;
2001-02-09 20:52:59 +01:00
}
2001-02-25 20:31:40 +01:00
hsum + + ;
}
for ( i = 0 ; i ! = 6 ; + + i ) herbs [ i ] = 0 ;
for ( r = regions ; r ; r = r - > next ) if ( rterrain ( r ) = = T_PLAIN ) {
const herb_type * htype = rherbtype ( r ) ;
assert ( htype ) ;
for ( i = 0 ; i ! = 6 ; + + i ) if ( htypes [ i ] = = htype ) break ;
assert ( i ! = 6 ) ;
herbs [ i ] + + ;
}
for ( i = 0 ; i ! = 6 ; + + i ) {
fprintf ( stderr , " %s : %d \n " , locale_string ( NULL , resourcename ( htypes [ i ] - > itype - > rtype , 0 ) ) , herbs [ i ] ) ;
2001-02-09 20:52:59 +01:00
}
}
2001-09-05 21:40:40 +02:00
# endif
2001-02-09 20:52:59 +01:00
2001-02-17 15:47:43 +01:00
2001-02-25 20:31:40 +01:00
# include <event.h>
# include <triggers/timeout.h>
# include <triggers/changerace.h>
# include <triggers/changefaction.h>
# include <triggers/createcurse.h>
# include <triggers/createunit.h>
# include <triggers/killunit.h>
# include <triggers/giveitem.h>
typedef struct handler_info {
char * event ;
trigger * triggers ;
} handler_info ;
typedef struct timeout_data {
trigger * triggers ;
int timer ;
variant trigger_data ;
} timeout_data ;
trigger *
get_timeout ( trigger * td , trigger * tfind )
{
trigger * t = td ;
while ( t ) {
if ( t - > type = = & tt_timeout ) {
timeout_data * tdata = ( timeout_data * ) t - > data . v ;
trigger * tr = tdata - > triggers ;
while ( tr ) {
if ( tr = = tfind ) break ;
tr = tr - > next ;
}
if ( tr = = tfind ) break ;
}
t = t - > next ;
}
return t ;
}
2001-09-05 21:40:40 +02:00
#if 0
2001-02-25 20:31:40 +01:00
static void
fix_timeouts ( void )
{
region * r ;
for ( r = regions ; r ; r = r - > next ) {
unit * u ;
for ( u = r - > units ; u ; u = u - > next ) {
attrib * a = a_find ( u - > attribs , & at_eventhandler ) ;
boolean toad = ( u - > race = = RC_TOAD ) ;
boolean keeper = ( u - > race = = RC_IRONKEEPER ) ;
while ( a ! = NULL ) {
trigger * t ;
handler_info * td = ( handler_info * ) a - > data . v ;
for ( t = td - > triggers ; t ; t = t - > next ) {
trigger * * tptr = & t - > next ;
while ( * tptr ) {
/* remove duplicates */
if ( ( * tptr ) - > type = = t - > type ) {
* tptr = ( * tptr ) - > next ;
} else tptr = & ( * tptr ) - > next ;
}
2001-04-01 08:58:45 +02:00
if ( t - > type = = & tt_changerace | |
t - > type = = & tt_changefaction | |
t - > type = = & tt_createcurse | |
t - > type = = & tt_createunit )
2001-02-25 20:31:40 +01:00
{
trigger * timer = get_timeout ( td - > triggers , t ) ;
if ( toad & & t - > type = = & tt_changerace ) {
toad = false ;
}
if ( timer = = NULL ) {
add_trigger ( & u - > attribs , " timer " , trigger_timeout ( 1 + ( rand ( ) % 2 ) , t ) ) ;
}
}
else if ( t - > type = = & tt_killunit ) {
if ( u - > race = = RC_IRONKEEPER ) {
trigger * timer = get_timeout ( td - > triggers , t ) ;
keeper = false ;
if ( timer = = NULL ) {
add_trigger ( & u - > attribs , " timer " , trigger_timeout ( 1 + ( rand ( ) % 2 ) , t ) ) ;
}
}
}
}
a = a - > nexttype ;
}
if ( keeper ) {
int duration = 1 + ( rand ( ) % 2 ) ;
trigger * tkill = trigger_killunit ( u ) ;
add_trigger ( & u - > attribs , " timer " , trigger_timeout ( duration , tkill ) ) ;
}
if ( toad ) {
/* repair toad-only mage */
int duration = 1 + ( rand ( ) % 2 ) ;
trigger * trestore = trigger_changerace ( u , u - > faction - > race , u - > faction - > race ) ;
if ( rand ( ) % 10 > 2 ) t_add ( & trestore , trigger_giveitem ( u , olditemtype [ I_TOADSLIME ] , 1 ) ) ;
add_trigger ( & u - > attribs , " timer " , trigger_timeout ( duration , trestore ) ) ;
}
}
}
}
2001-09-05 21:40:40 +02:00
# endif
2001-02-25 20:31:40 +01:00
2001-04-01 08:58:45 +02:00
# include <modules/gmcmd.h>
2001-12-10 01:13:39 +01:00
2002-03-02 16:26:45 +01:00
static int
2002-03-12 23:40:23 +01:00
resize_plane ( struct plane * p , int radius )
2002-03-02 16:26:45 +01:00
{
region * center = findregion ( p - > minx + ( p - > maxx - p - > minx ) / 2 , p - > miny + ( p - > maxy - p - > miny ) / 2 ) ;
2002-03-24 13:43:12 +01:00
int x , y , minx , maxx , miny , maxy ;
if ( ! center ) return 0 ;
minx = center - > x - radius ;
maxx = center - > x + radius ;
miny = center - > y - radius ;
maxy = center - > y + radius ;
2002-03-12 23:40:23 +01:00
for ( x = minx ; x < = maxx ; + + x ) {
for ( y = miny ; y < = maxy ; + + y ) {
region * r = findregion ( x , y ) ;
if ( r & & rplane ( r ) ! = p ) break ;
}
}
if ( x < = maxx ) return - 1 ;
p - > maxx = maxx ;
p - > maxy = maxy ;
p - > minx = minx ;
p - > miny = miny ;
for ( x = minx ; x < = maxx ; + + x ) {
for ( y = miny ; y < = maxy ; + + y ) {
region * r = findregion ( x , y ) ;
if ( r = = NULL ) {
2002-03-24 11:22:27 +01:00
r = new_region ( x , y ) ;
2002-03-12 23:40:23 +01:00
freset ( r , RF_ENCOUNTER ) ;
r - > planep = p ;
if ( distance ( r , center ) = = radius ) {
terraform ( r , T_FIREWALL ) ;
} else if ( distance ( r , center ) < radius ) {
terraform ( r , T_OCEAN ) ;
}
2002-04-14 10:22:35 +02:00
} else if ( rterrain ( r ) = = T_FIREWALL & & distance ( r , center ) ! = radius ) {
terraform ( r , T_OCEAN ) ;
2002-03-12 23:40:23 +01:00
}
}
}
2002-03-02 16:26:45 +01:00
return 0 ;
}
2002-03-12 23:40:23 +01:00
static int
regatta_quest ( void )
{
plane * p = getplanebyname ( " Regatta " ) ;
if ( p ) {
2002-05-05 12:26:33 +02:00
fset ( p , PFL_NOMONSTERS ) ;
2002-03-29 05:23:51 +01:00
fset ( p , PFL_SEESPECIAL ) ;
2002-03-12 23:40:23 +01:00
return resize_plane ( p , 40 ) ;
2002-04-14 10:22:35 +02:00
# ifdef REGATTA_QUESTMASTER /* "gregorjochmann@gmx.de" */
2002-03-12 23:40:23 +01:00
} else {
region * center ;
2002-05-05 12:26:33 +02:00
p = gm_addplane ( 40 , PFL_NORECRUITS | PFL_NOMONSTERS | PFL_SEESPECIAL , " Regatta " ) ;
2002-03-12 23:40:23 +01:00
center = findregion ( p - > minx + ( p - > maxx - p - > minx ) / 2 , p - > miny + ( p - > maxy - p - > miny ) / 2 ) ;
2002-04-14 10:22:35 +02:00
gm_addfaction ( REGATTA_QUESTMASTER , p , center ) ;
# endif
2002-03-12 23:40:23 +01:00
}
2002-04-14 10:22:35 +02:00
return 0 ;
2002-03-12 23:40:23 +01:00
}
2001-12-10 01:13:39 +01:00
static int
secondfaction ( faction * pf )
{
unit * u = findunit ( atoi36 ( " 5q9w " ) ) ;
if ( u ! = NULL ) {
plane * p = rplane ( u - > region ) ;
if ( p ! = NULL ) {
region * center = findregion ( ( p - > maxx - p - > minx ) / 2 , ( p - > maxy - p - > miny ) / 2 ) ;
if ( center ! = NULL ) {
gm_addfaction ( pf - > email , p , center ) ;
return 0 ;
}
}
}
return - 1 ;
}
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
static void
update_gmquests ( void )
{
2001-09-05 21:40:40 +02:00
faction * f = findfaction ( atoi36 ( " gm04 " ) ) ;
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
if ( f ) {
unit * u = f - > units ;
2001-12-10 01:13:39 +01:00
potion_t p ;
attrib * permissions = a_find ( f - > attribs , & at_permissions ) ;
2001-09-05 21:40:40 +02:00
if ( u ! = NULL ) {
plane * p = rplane ( u - > region ) ;
2002-03-12 21:48:10 +01:00
/* gm04 will keine Orks */
2001-09-05 21:40:40 +02:00
if ( p ! = NULL ) p - > flags | = PFL_NOORCGROWTH ;
2002-03-12 21:48:10 +01:00
/* gm04 will keine Monster */
if ( p ! = NULL ) p - > flags | = PFL_NOMONSTERS ;
2001-09-05 21:40:40 +02:00
}
2001-12-10 01:13:39 +01:00
for ( p = 0 ; p ! = MAX_POTIONS ; + + p ) {
attrib * a = a_find ( permissions , & at_gmcreate ) ;
while ( a & & a - > data . v ! = ( void * ) oldpotiontype [ p ] - > itype ) a = a - > nexttype ;
if ( ! a ) a_add ( ( attrib * * ) & permissions - > data . v , make_atgmcreate ( oldpotiontype [ p ] - > itype ) ) ;
}
2002-03-12 21:48:10 +01:00
do_once ( " et02 " , secondfaction ( f ) ) ;
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
}
2002-03-12 23:40:23 +01:00
do_once ( " rq02 " , regatta_quest ( ) ) ;
2002-04-14 10:22:35 +02:00
do_once ( " rq03 " , regatta_quest ( ) ) ;
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
}
2001-09-05 21:40:40 +02:00
#if 0
2001-04-01 08:58:45 +02:00
static void
test_gmquest ( void )
{
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
const struct faction * f ;
/* enno's world */
f = gm_addquest ( " enno@eressea.upb.de " , " GM Zone " , 1 , PFL_NOATTACK | PFL_NOALLIANCES | PFL_NOFEED | PFL_FRIENDLY ) ;
log_printf ( " Neue Questenpartei %s \n " , factionname ( f ) ) ;
2001-04-01 08:58:45 +02:00
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
f = gm_addquest ( " xandril@att.net " , " Mardallas Welt " , 40 , 0 ) ;
log_printf ( " Neue Questenpartei %s \n " , factionname ( f ) ) ;
2001-04-01 08:58:45 +02:00
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
f = gm_addquest ( " moritzsalinger@web.de " , " Laen-Kaiser " , 7 , /*PFL_NORECRUITS |*/ PFL_NOMAGIC /*| PFL_NOBUILD*/ ) ;
log_printf ( " Neue Questenpartei %s \n " , factionname ( f ) ) ;
2001-04-01 08:58:45 +02:00
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
f = gm_addquest ( " Denise.Muenstermann@home.gelsen-net.de " , " Mochikas Queste " , 7 , PFL_NOMAGIC ) ;
log_printf ( " Neue Questenpartei %s \n " , factionname ( f ) ) ;
2001-04-01 08:58:45 +02:00
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
f = gm_addquest ( " feeron@aol.com " , " Eternath " , 11 , 0 ) ;
log_printf ( " Neue Questenpartei %s \n " , factionname ( f ) ) ;
2001-09-05 21:40:40 +02:00
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
f = gm_addquest ( " BigBear@nord-com.net " , " Leonidas Verm<72> chtnis " , 15 , PFL_NOMAGIC | PFL_NOSTEALTH ) ;
log_printf ( " Neue Questenpartei %s \n " , factionname ( f ) ) ;
2001-04-01 08:58:45 +02:00
}
2001-09-05 21:40:40 +02:00
# endif
2001-04-01 08:58:45 +02:00
2001-04-16 16:34:19 +02:00
# define TEST_LOCALES 0
# if TEST_LOCALES
static void
2001-09-05 21:40:40 +02:00
setup_locales ( void )
2001-04-16 16:34:19 +02:00
{
locale * lang = find_locale ( " en " ) ;
faction * f = factions ;
while ( f ) {
f - > locale = lang ;
f = f - > next ;
}
}
# endif
2001-04-22 20:14:07 +02:00
# include <triggers/shock.h>
# include <triggers/killunit.h>
2001-12-10 01:13:39 +01:00
#if 0
# error "this is broken, it duplicates triggers"
2001-04-22 20:14:07 +02:00
static void
fix_unitrefs ( void )
{
region * r = regions ;
while ( r ) {
unit * u = r - > units ;
while ( u ) {
attrib * a ;
a = a_find ( u - > attribs , & at_familiar ) ;
if ( a ) {
/* magier, hat einen familiar */
unit * ufamiliar = get_familiar ( u ) ;
if ( ufamiliar ) {
attrib * ae ;
/* killunit attribut am magier */
ae = a_find ( u - > attribs , & at_eventhandler ) ;
if ( ae ) {
trigger * tkillunit = NULL ;
trigger * * tlist = get_triggers ( u - > attribs , " destroy " ) ;
if ( tlist ! = NULL ) {
tkillunit = * tlist ;
while ( tkillunit ) {
if ( strcmp ( tkillunit - > type - > name , " killunit " ) = = 0 ) break ;
tkillunit = tkillunit - > next ;
}
if ( tkillunit & & ! tkillunit - > data . v ) {
2001-09-05 21:40:40 +02:00
log_warning ( ( " killunit-trigger f<> r Magier %s und Vertrauten %s restauriert. \n " ,
2001-04-22 20:14:07 +02:00
itoa36 ( u - > no ) , itoa36 ( ufamiliar - > no ) ) ) ;
tkillunit - > data . v = ufamiliar ;
}
else ae = NULL ;
}
}
if ( ae = = NULL ) {
/* Wenn der Magier stirbt, dann auch der Vertraute */
add_trigger ( & u - > attribs , " destroy " , trigger_killunit ( ufamiliar ) ) ;
}
/* killunit attribut am magier */
ae = a_find ( ufamiliar - > attribs , & at_eventhandler ) ;
if ( ae ) {
trigger * tshockunit = NULL ;
trigger * * tlist = get_triggers ( ufamiliar - > attribs , " destroy " ) ;
if ( tlist ! = NULL ) {
tshockunit = * tlist ;
while ( tshockunit ) {
if ( strcmp ( tshockunit - > type - > name , " shock " ) = = 0 ) break ;
tshockunit = tshockunit - > next ;
}
if ( tshockunit & & ! tshockunit - > data . v ) {
2001-09-05 21:40:40 +02:00
log_warning ( ( " shockunit-trigger f<> r Magier %s und Vertrauten %s restauriert. \n " ,
2001-04-22 20:14:07 +02:00
itoa36 ( u - > no ) , itoa36 ( ufamiliar - > no ) ) ) ;
tshockunit - > data . v = u ;
}
else ae = NULL ;
}
}
if ( ae = = NULL ) {
/* Wenn der Vertraute stirbt, schockt er den Magier */
add_trigger ( & ufamiliar - > attribs , " destroy " , trigger_shock ( u ) ) ;
}
} else {
2001-09-05 21:40:40 +02:00
log_error ( ( " Magier %s hat ein at_familiar, aber keinen Vertrauten. \n " ,
2001-04-22 20:14:07 +02:00
itoa36 ( u - > no ) ) ) ;
}
}
u = u - > next ;
}
r = r - > next ;
}
}
2001-12-10 01:13:39 +01:00
# endif
2001-04-22 20:14:07 +02:00
2001-09-05 21:40:40 +02:00
static void
update_igjarjuk_quest ( void )
{
unit * u ;
faction * f = findfaction ( atoi36 ( " rr " ) ) ;
if ( ! f ) return ;
for ( u = f - > units ; u ; u = u - > nextF ) {
2001-12-10 01:13:39 +01:00
u - > race = new_race [ RC_TEMPLATE ] ;
2001-09-05 21:40:40 +02:00
}
}
2001-12-10 01:13:39 +01:00
2001-12-15 13:26:04 +01:00
# if RESOURCE_CONVERSION
2001-12-10 01:13:39 +01:00
extern struct attrib_type at_resources ;
void
init_resourcefix ( void )
{
at_register ( & at_resources ) ;
}
static int
read_resfix ( void )
{
#if 0
FILE * F = fopen ( " resource.fix " , " r " ) ;
if ( F = = NULL ) return ;
while ( ! feof ( F ) ) {
int x , y , stone , iron , laen , age ;
int lstone , liron , llaen ; /* level */
region * r ;
fscanf ( F , " %d %d %d %d %d %d %d %d %d \n " , & x , & y , & age , & stone , & iron , & laen , & lstone , & liron , & llaen ) ;
r = findregion ( x , y ) ;
if ( r ) {
rawmaterial * rm = r - > resources ;
while ( rm ) {
if ( rm - > type = = & rm_iron & & liron > 0 ) {
rm - > amount = iron ;
rm - > level = liron ;
}
else if ( rm - > type = = & rm_laen & & llaen > 0 ) {
rm - > amount = laen ;
rm - > level = llaen ;
}
else if ( rm - > type = = & rm_stones & & lstone > 0 ) {
rm - > amount = stone ;
rm - > level = lstone ;
}
rm = rm - > next ;
}
r - > age = ( unsigned short ) age ;
}
}
fclose ( F ) ;
# else
return - 1 ;
# endif
}
static int
convert_resources ( void )
{
#if 0
region * r ;
for ( r = regions ; r ; r = r - > next ) {
attrib * a = a_find ( r - > attribs , & at_resources ) ;
r - > resources = 0 ;
terraform_resources ( r ) ;
if ( a = = NULL ) continue ;
else {
int INIT_STONE = 20 ; /* skip this many weeks */
double ironmulti = 0.40 ;
double laenmulti = 0.50 ;
double stonemulti = 0.30 ; /* half the stones used */
rawmaterial * rmiron = rm_get ( r , rm_iron . rtype ) ;
rawmaterial * rmlaen = rm_get ( r , rm_laen . rtype ) ;
rawmaterial * rmstone = rm_get ( r , rm_stones . rtype ) ;
int oldiron ;
int oldlaen = MAXLAENPERTURN * min ( r - > age , 100 ) / 2 ;
int oldstone = terrain [ rterrain ( r ) ] . quarries * max ( 0 , r - > age - INIT_STONE ) ;
int iron = a - > data . sa [ 0 ] ;
int laen = a - > data . sa [ 1 ] ;
int stone , level ;
int i , base ;
/** STONE **/
for ( i = 0 ; terrain [ r - > terrain ] . rawmaterials [ i ] . type ; + + i ) {
if ( terrain [ r - > terrain ] . rawmaterials [ i ] . type = = & rm_stones ) break ;
}
if ( terrain [ r - > terrain ] . rawmaterials [ i ] . type ) {
base = terrain [ r - > terrain ] . rawmaterials [ i ] . base ;
stone = max ( 0 , ( int ) ( oldstone * stonemulti ) ) ;
level = 1 ;
base = ( int ) ( terrain [ r - > terrain ] . rawmaterials [ i ] . base * ( 1 + level * terrain [ r - > terrain ] . rawmaterials [ i ] . divisor ) ) ;
while ( stone > = base ) {
stone - = base ;
+ + level ;
base = ( int ) ( terrain [ r - > terrain ] . rawmaterials [ i ] . base * ( 1 + level * terrain [ r - > terrain ] . rawmaterials [ i ] . divisor ) ) ;
}
rmstone - > level = level ;
rmstone - > amount = base - stone ;
assert ( rmstone - > amount > 0 ) ;
log_printf ( " CONVERSION: %d stones @ level %d in %s \n " , rmstone - > amount , rmstone - > level , regionname ( r , NULL ) ) ;
} else {
log_error ( ( " found stones in %s of %s \n " , terrain [ r - > terrain ] . name , regionname ( r , NULL ) ) ) ;
}
/** IRON **/
if ( r_isglacier ( r ) | | r - > terrain = = T_ICEBERG ) {
oldiron = GLIRONPERTURN * min ( r - > age , 100 ) / 2 ;
} else {
oldiron = IRONPERTURN * r - > age ;
}
for ( i = 0 ; terrain [ r - > terrain ] . rawmaterials [ i ] . type ; + + i ) {
if ( terrain [ r - > terrain ] . rawmaterials [ i ] . type = = & rm_iron ) break ;
}
if ( terrain [ r - > terrain ] . rawmaterials [ i ] . type ) {
base = terrain [ r - > terrain ] . rawmaterials [ i ] . base ;
iron = max ( 0 , ( int ) ( oldiron * ironmulti - iron ) ) ;
level = 1 ;
base = ( int ) ( terrain [ r - > terrain ] . rawmaterials [ i ] . base * ( 1 + level * terrain [ r - > terrain ] . rawmaterials [ i ] . divisor ) ) ;
while ( iron > = base ) {
iron - = base ;
+ + level ;
base = ( int ) ( terrain [ r - > terrain ] . rawmaterials [ i ] . base * ( 1 + level * terrain [ r - > terrain ] . rawmaterials [ i ] . divisor ) ) ;
}
rmiron - > level = level ;
rmiron - > amount = base - iron ;
assert ( rmiron - > amount > 0 ) ;
log_printf ( " CONVERSION: %d iron @ level %d in %s \n " , rmiron - > amount , rmiron - > level , regionname ( r , NULL ) ) ;
} else {
log_error ( ( " found iron in %s of %s \n " , terrain [ r - > terrain ] . name , regionname ( r , NULL ) ) ) ;
}
/** LAEN **/
if ( laen > = 0 ) {
if ( rmlaen = = NULL ) {
rmlaen = calloc ( sizeof ( rawmaterial ) , 1 ) ;
rmlaen - > next = r - > resources ;
r - > resources = rmlaen ;
}
for ( i = 0 ; terrain [ r - > terrain ] . rawmaterials [ i ] . type ; + + i ) {
if ( terrain [ r - > terrain ] . rawmaterials [ i ] . type = = & rm_laen ) break ;
}
if ( terrain [ r - > terrain ] . rawmaterials [ i ] . type ) {
laen = max ( 0 , ( int ) ( oldlaen * laenmulti - laen ) ) ;
level = 1 ;
base = ( int ) ( terrain [ r - > terrain ] . rawmaterials [ i ] . base * ( 1 + level * terrain [ r - > terrain ] . rawmaterials [ i ] . divisor ) ) ;
while ( laen > = base ) {
laen - = base ;
+ + level ;
base = ( int ) ( terrain [ r - > terrain ] . rawmaterials [ i ] . base * ( 1 + level * terrain [ r - > terrain ] . rawmaterials [ i ] . divisor ) ) ;
}
rmlaen - > level = level ;
rmlaen - > amount = base - laen ;
assert ( rmlaen - > amount > 0 ) ;
log_printf ( " CONVERSION: %d laen @ level %d in %s \n " , rmlaen - > amount , rmlaen - > level , regionname ( r , NULL ) ) ;
rmlaen = NULL ;
}
}
if ( rmlaen ) {
struct rawmaterial * res ;
struct rawmaterial * * pres = & r - > resources ;
if ( laen ! = - 1 ) log_error ( ( " found laen in %s of %s \n " , terrain [ r - > terrain ] . name , regionname ( r , NULL ) ) ) ;
while ( * pres ! = rmlaen ) pres = & ( * pres ) - > next ;
res = * pres ;
* pres = ( * pres ) - > next ;
free ( res ) ;
}
# ifndef NDEBUG
{
rawmaterial * res = r - > resources ;
while ( res ) {
assert ( res - > amount > 0 ) ;
assert ( res - > level > 0 ) ;
res = res - > next ;
}
}
# endif
}
}
return 0 ;
# else
return - 1 ;
# endif
}
# endif
#if 0
static int
convert_resources ( void )
2001-09-05 21:40:40 +02:00
{
region * r ;
attrib * a ;
for ( r = regions ; r ; r = r - > next ) {
/* Iron */
if ( rterrain ( r ) = = T_MOUNTAIN ) {
a_add ( & r - > attribs , a_new ( & at_iron ) ) - > data . i = 25 ;
} else if ( rterrain ( r ) = = T_GLACIER | | rterrain ( r ) = = T_ICEBERG_SLEEP ) {
a_add ( & r - > attribs , a_new ( & at_iron ) ) - > data . i = 2 ;
}
/* Laen */
if ( rterrain ( r ) = = T_MOUNTAIN ) {
a = a_find ( r - > attribs , & at_laen ) ;
if ( a ) a - > data . i = 6 ;
}
/* Stone */
if ( terrain [ rterrain ( r ) ] . quarries > 0 ) {
a_add ( & r - > attribs , a_new ( & at_stone ) ) - > data . i = terrain [ rterrain ( r ) ] . quarries ;
}
}
2001-12-10 01:13:39 +01:00
return 0 ;
}
static void
fix_negpotion ( void )
{
region * r ;
unit * u ;
int i ;
for ( r = regions ; r ; r = r - > next ) {
for ( u = r - > units ; u ; u = u - > next ) {
i = get_effect ( u , oldpotiontype [ P_FAST ] ) ;
if ( i < 0 ) {
change_effect ( u , oldpotiontype [ P_FAST ] , - i ) ;
}
}
}
}
2002-01-21 02:20:45 +01:00
# endif
2001-12-10 01:13:39 +01:00
2001-12-15 13:26:04 +01:00
# if GROWING_TREES
2001-12-10 01:13:39 +01:00
int
growing_trees ( void )
{
region * r ;
for ( r = regions ; r ; r = r - > next ) {
if ( rtrees ( r , 2 ) ) {
rsettrees ( r , 1 , rtrees ( r , 2 ) / 4 ) ;
rsettrees ( r , 0 , rtrees ( r , 2 ) / 2 ) ;
}
}
return 0 ;
2001-09-05 21:40:40 +02:00
}
# endif
2001-12-10 01:13:39 +01:00
# include <triggers/gate.h>
# include <triggers/unguard.h>
typedef struct gate_data {
struct building * gate ;
struct region * target ;
} gate_data ;
static void
fix_gates ( void )
{
region * r ;
for ( r = regions ; r ; r = r - > next ) {
unit * u ;
building * b ;
for ( u = r - > units ; u ; u = u - > next ) {
trigger * * triggers = get_triggers ( u - > attribs , " timer " ) ;
if ( triggers ) {
trigger * t = * triggers ;
while ( t & & t - > type ! = & tt_gate ) t = t - > next ;
if ( t ! = NULL ) {
gate_data * gd = ( gate_data * ) t - > data . v ;
struct building * b = gd - > gate ;
struct region * rtarget = gd - > target ;
if ( r ! = b - > region ) {
add_trigger ( & b - > attribs , " timer " , trigger_gate ( b , rtarget ) ) ;
add_trigger ( & b - > attribs , " create " , trigger_unguard ( b ) ) ;
fset ( b , BLD_UNGUARDED ) ;
}
}
remove_triggers ( & u - > attribs , " timer " , & tt_gate ) ;
remove_triggers ( & u - > attribs , " create " , & tt_unguard ) ;
}
}
for ( b = r - > buildings ; b ; b = b - > next ) {
trigger * * triggers = get_triggers ( b - > attribs , " timer " ) ;
if ( triggers ) {
trigger * t = * triggers ;
while ( t & & t - > type ! = & tt_gate ) t = t - > next ;
if ( t ! = NULL ) {
gate_data * gd = ( gate_data * ) t - > data . v ;
struct building * b = gd - > gate ;
struct region * rtarget = gd - > target ;
remove_triggers ( & b - > attribs , " timer " , & tt_gate ) ;
remove_triggers ( & b - > attribs , " create " , & tt_unguard ) ;
if ( r ! = b - > region ) {
add_trigger ( & b - > attribs , " timer " , trigger_gate ( b , rtarget ) ) ;
add_trigger ( & b - > attribs , " create " , trigger_unguard ( b ) ) ;
fset ( b , BLD_UNGUARDED ) ;
}
}
}
}
}
}
static int
dump_sql ( void )
{
faction * f ;
for ( f = factions ; f ; f = f - > next ) {
if ( f - > unique_id = = 0 ) {
f - > unique_id = + + max_unique_id ;
}
}
return 0 ;
}
2001-12-15 13:26:04 +01:00
# if NEW_RESOURCEGROWTH
2001-12-10 01:13:39 +01:00
static int
randomized_resources ( void )
{
region * r ;
for ( r = regions ; r ; r = r - > next ) if ( r - > land ) {
terrain_t ter = rterrain ( r ) ;
/* Dieses if verhindert, das Laen nocheinmal verteilt wird. */
if ( ter = = T_MOUNTAIN | | ter = = T_GLACIER | | ter = = T_ICEBERG | | ter = = T_ICEBERG_SLEEP ) continue ;
terraform_resources ( r ) ;
}
return 0 ;
}
2001-12-15 13:26:04 +01:00
# endif
2001-12-10 01:13:39 +01:00
2001-12-23 10:23:53 +01:00
static int
fix_idleout ( void )
{
faction * f ;
f = findfaction ( 0 ) ;
2001-12-23 10:31:08 +01:00
if ( f ) {
fset ( f , FL_NOIDLEOUT ) ;
}
2001-12-23 10:23:53 +01:00
f = findfaction ( atoi36 ( " muse " ) ) ;
2001-12-23 10:31:08 +01:00
if ( f ) {
fset ( f , FL_NOIDLEOUT ) ;
}
2001-12-23 10:23:53 +01:00
return 0 ;
}
2002-01-13 08:59:41 +01:00
static int
set_zip ( void )
{
faction * f ;
for ( f = factions ; f ; f = f - > next ) {
if ( ! ( f - > options & ( 1 < < O_BZIP2 ) ) & & ! ( f - > options & ( 1 < < O_COMPRESS ) ) ) {
f - > options = f - > options | ( 1 < < O_COMPRESS ) ;
}
}
2002-01-13 09:18:03 +01:00
f = findfaction ( 0 ) ;
2002-01-20 13:53:35 +01:00
f - > options = f - > options & ~ ( 1 < < O_COMPRESS ) ;
2002-01-13 09:18:03 +01:00
f - > options = f - > options | ( 1 < < O_BZIP2 ) ;
2002-01-13 08:59:41 +01:00
return 0 ;
}
2002-01-20 11:26:38 +01:00
static int
heal_all ( void )
{
region * r ;
unit * u ;
2002-01-20 11:38:03 +01:00
faction * f ;
2002-01-20 13:53:35 +01:00
message * msg = msg_message ( " healall " , " " ) ;
2002-01-20 11:38:03 +01:00
for ( f = factions ; f ; f = f - > next ) {
freset ( f , FL_DH ) ;
}
2002-01-20 11:26:38 +01:00
for ( r = regions ; r ; r = r - > next ) {
for ( u = r - > units ; u ; u = u - > next ) {
int max_hp = unit_max_hp ( u ) * u - > number ;
2002-05-02 23:19:45 +02:00
if ( u - > hp < max_hp ) {
2002-01-20 11:26:38 +01:00
u - > hp = max_hp ;
2002-01-20 11:38:03 +01:00
fset ( u - > faction , FL_DH ) ;
2002-05-02 23:19:45 +02:00
}
2002-01-20 11:26:38 +01:00
}
}
2002-05-02 23:19:45 +02:00
2002-01-20 12:35:06 +01:00
for ( f = factions ; f ; f = f - > next ) {
2002-01-20 11:38:03 +01:00
if ( fval ( f , FL_DH ) ) {
2002-01-20 12:35:06 +01:00
add_message ( & f - > msgs , msg ) ;
2002-01-20 11:38:03 +01:00
freset ( f , FL_DH ) ;
}
}
2002-01-20 12:35:06 +01:00
msg_release ( msg ) ;
2002-01-20 11:38:03 +01:00
return 0 ;
2002-01-20 11:26:38 +01:00
}
2002-02-03 13:56:15 +01:00
# if PEASANT_ADJUSTMENT == 1
2002-02-02 20:00:56 +01:00
# define WEIGHT ((double)0.5)
2002-02-10 18:23:00 +01:00
# define PLWEIGHT ((double)0.80)
2002-02-02 20:00:56 +01:00
2002-02-02 15:55:14 +01:00
static int
peasant_adjustment ( void )
{
terrain_t ter ;
int sum , avg , c ;
2002-02-03 03:36:12 +01:00
double freeall , pool ; /* long long is illegal */
2002-02-18 22:41:11 +01:00
double s ;
2002-02-18 17:19:50 +01:00
region * r ;
2002-02-02 15:55:14 +01:00
2002-02-18 17:19:50 +01:00
s = 0 ;
for ( r = regions ; r ; r = r - > next ) {
s + = rpeasants ( r ) ;
}
log_printf ( " BAUERN vorher: %lld \n " , s ) ;
2002-02-02 15:55:14 +01:00
2002-02-18 17:19:50 +01:00
for ( ter = 0 ; ter < MAXTERRAINS ; ter + + ) {
2002-02-02 15:55:14 +01:00
if ( terrain [ ter ] . production_max < = 0 ) continue ;
2002-02-02 20:00:56 +01:00
c = 0 ;
2002-02-02 15:55:14 +01:00
sum = 0 ;
pool = 0 ;
freeall = 0 ;
for ( r = regions ; r ; r = r - > next ) if ( rterrain ( r ) = = ter ) {
unit * u ;
c + + ;
sum + = rpeasants ( r ) ;
for ( u = r - > units ; u ; u = u - > next ) {
if ( lifestyle ( u ) > 0 ) sum + = u - > number ;
2002-02-10 20:38:37 +01:00
/* Sonderregel Bauernmob */
if ( u - > race = = new_race [ RC_PEASANT ] ) sum + = u - > number ;
2002-02-02 15:55:14 +01:00
}
}
2002-02-03 03:40:37 +01:00
if ( c = = 0 ) continue ;
2002-02-02 15:55:14 +01:00
avg = sum / c ;
2002-05-02 23:19:45 +02:00
2002-02-02 15:55:14 +01:00
for ( r = regions ; r ; r = r - > next ) if ( rterrain ( r ) = = ter ) {
unit * u ;
int playerp = 0 ;
int p_weg ;
2002-02-02 20:00:56 +01:00
int soll ;
2002-02-02 15:55:14 +01:00
for ( u = r - > units ; u ; u = u - > next ) {
if ( lifestyle ( u ) > 0 ) playerp + = u - > number ;
2002-02-10 20:38:37 +01:00
/* Sonderregel Bauernmob */
if ( u - > race = = new_race [ RC_PEASANT ] ) playerp + = u - > number ;
2002-02-02 15:55:14 +01:00
}
2002-02-02 20:00:56 +01:00
2002-02-03 03:36:12 +01:00
soll = ( int ) ( ( avg + playerp + rpeasants ( r ) ) * WEIGHT ) ;
2002-02-02 20:00:56 +01:00
2002-02-02 23:17:46 +01:00
if ( playerp * PLWEIGHT + rpeasants ( r ) > soll ) {
2002-02-03 03:36:12 +01:00
p_weg = ( int ) ( min ( ( ( playerp * PLWEIGHT ) + rpeasants ( r ) ) - soll , rpeasants ( r ) ) ) ;
2002-02-02 20:00:56 +01:00
assert ( p_weg > = 0 ) ;
2002-02-02 23:17:46 +01:00
if ( p_weg > 0 ) {
2002-02-17 12:13:48 +01:00
log_printf ( " BAUERN %s: war %d, minus %d, playerp %d \n " ,
regionname ( r , NULL ) , rpeasants ( r ) , p_weg , playerp ) ;
2002-02-02 23:17:46 +01:00
}
2002-02-02 20:00:56 +01:00
pool + = p_weg ;
rsetpeasants ( r , rpeasants ( r ) - p_weg ) ;
assert ( rpeasants ( r ) > = 0 ) ;
}
2002-02-02 15:55:14 +01:00
freeall + = max ( 0 , production ( r ) * MAXPEASANTS_PER_AREA
- ( ( rtrees ( r , 2 ) + rtrees ( r , 1 ) / 2 ) * TREESIZE ) - playerp ) ;
}
2002-05-02 23:19:45 +02:00
2002-02-02 15:55:14 +01:00
for ( r = regions ; r ; r = r - > next ) if ( rterrain ( r ) = = ter ) {
unit * u ;
2002-02-03 03:36:12 +01:00
double free ;
2002-02-02 15:55:14 +01:00
int newp ;
int playerp = 0 ;
2002-05-02 23:19:45 +02:00
2002-02-02 15:55:14 +01:00
for ( u = r - > units ; u ; u = u - > next ) {
if ( lifestyle ( u ) > 0 ) playerp + = u - > number ;
2002-02-10 20:38:37 +01:00
/* Sonderregel Bauernmob */
if ( u - > race = = new_race [ RC_PEASANT ] ) playerp + = u - > number ;
2002-02-02 15:55:14 +01:00
}
free = max ( 0 , production ( r ) * MAXPEASANTS_PER_AREA
- ( ( rtrees ( r , 2 ) + rtrees ( r , 1 ) / 2 ) * TREESIZE ) - playerp ) ;
2002-02-03 03:36:12 +01:00
newp = ( int ) ( ( pool * free ) / freeall ) ;
2002-02-02 15:55:14 +01:00
rsetpeasants ( r , rpeasants ( r ) + newp ) ;
2002-02-02 20:00:56 +01:00
assert ( rpeasants ( r ) > = 0 ) ;
2002-02-02 15:55:14 +01:00
}
}
2002-05-02 23:19:45 +02:00
2002-02-18 17:19:50 +01:00
s = 0 ;
for ( r = regions ; r ; r = r - > next ) {
s + = rpeasants ( r ) ;
}
log_printf ( " BAUERN nachher: %lld \n " , s ) ;
2002-02-02 15:55:14 +01:00
return 0 ;
}
2002-02-10 18:56:03 +01:00
static int
2002-03-09 16:16:35 +01:00
orc_conversion2 ( void )
2002-02-10 18:56:03 +01:00
{
2002-03-09 16:16:35 +01:00
faction * f ;
unit * u ;
region * r ;
for ( f = factions ; f ; f = f - > next ) {
if ( f - > race = = new_race [ RC_ORC ] ) {
f - > race = new_race [ RC_URUK ] ;
}
}
2002-02-10 18:56:03 +01:00
2002-03-09 16:16:35 +01:00
for ( r = regions ; r ; r = r - > next ) {
for ( u = r - > units ; u ; u = u - > next ) {
if ( u - > race = = new_race [ RC_ORC ] | | u - > race = = new_race [ RC_SNOTLING ] ) {
/* convert to either uruk or snotling */
if ( has_skill ( u , SK_MAGIC ) | | has_skill ( u , SK_ALCHEMY ) ) {
u - > race = new_race [ RC_URUK ] ;
u - > irace = new_race [ RC_URUK ] ;
}
2002-02-10 19:18:46 +01:00
}
2002-02-10 21:20:16 +01:00
}
2002-03-09 16:16:35 +01:00
}
2002-02-10 21:20:16 +01:00
2002-03-09 16:16:35 +01:00
return 0 ;
}
static int
orc_conversion ( void )
{
faction * f ;
unit * u ;
region * r ;
for ( f = factions ; f ; f = f - > next ) {
if ( f - > race = = new_race [ RC_ORC ] ) {
f - > race = new_race [ RC_URUK ] ;
}
}
for ( r = regions ; r ; r = r - > next ) {
for ( u = r - > units ; u ; u = u - > next ) {
if ( u - > race = = new_race [ RC_ORC ] ) {
/* convert to either uruk or snotling */
if ( effskill ( u , SK_MAGIC ) > = 1
| | effskill ( u , SK_ALCHEMY ) > = 1
| | get_item ( u , I_CHASTITY_BELT ) > = u - > number ) {
u - > race = new_race [ RC_URUK ] ;
u - > irace = new_race [ RC_URUK ] ;
} else {
u - > race = new_race [ RC_SNOTLING ] ;
u - > irace = new_race [ RC_SNOTLING ] ;
2002-02-10 18:56:03 +01:00
}
}
}
2002-03-09 16:16:35 +01:00
}
2002-02-10 18:57:21 +01:00
2002-03-09 16:16:35 +01:00
return 0 ;
2002-02-10 18:56:03 +01:00
}
2002-02-02 15:55:14 +01:00
# endif
2002-01-28 02:55:31 +01:00
static int
2002-01-28 01:25:32 +01:00
fix_astralplane ( void )
{
plane * astralplane = getplanebyname ( " Astralraum " ) ;
2002-02-18 22:41:11 +01:00
if ( astralplane ) {
freset ( astralplane , PFL_NOCOORDS ) ;
set_ursprung ( findfaction ( MONSTER_FACTION ) , astralplane - > id , 0 , 0 ) ;
}
return 0 ;
}
static int
fix_watchers ( void )
{
2002-04-21 13:39:47 +02:00
plane * p = getplanebyid ( 1094969858 ) ;
2002-02-18 22:41:11 +01:00
if ( p ) {
2002-04-21 13:39:47 +02:00
faction * f = findfaction ( atoi36 ( " rega " ) ) ;
2002-02-18 22:41:11 +01:00
watcher * w = calloc ( sizeof ( watcher ) , 1 ) ;
w - > faction = f ;
w - > mode = see_unit ;
w - > next = p - > watchers ;
p - > watchers = w ;
}
2002-01-28 02:55:31 +01:00
return 0 ;
2002-01-28 01:25:32 +01:00
}
2002-02-10 08:53:54 +01:00
static int
fix_questcoors ( void )
{
plane * p = getplanebyid ( 59034966 ) ;
if ( p ) {
faction * f ;
region * eternath = findregion ( - 8750 , 3631 ) ;
if ( eternath ) for ( f = factions ; f ; f = f - > next ) {
ursprung * u = f - > ursprung ;
while ( u ) {
if ( u - > id = = p - > id ) {
2002-02-16 11:37:18 +01:00
u - > x = 0 ;
u - > y = 0 ;
2002-02-10 08:53:54 +01:00
break ;
}
u = u - > next ;
}
}
}
return 0 ;
}
2002-03-09 16:16:35 +01:00
static int
warn_password ( void )
{
faction * f = factions ;
while ( f ) {
boolean pwok = true ;
const char * c = f - > passw ;
while ( * c ) {
if ( ! isalnum ( * c ) ) pwok = false ;
c + + ;
}
if ( pwok = = false ) {
2002-05-02 23:19:45 +02:00
ADDMSG ( & f - > msgs , msg_message ( " msg_errors " , " string " ,
2002-03-09 16:16:35 +01:00
" Dein Passwort enth<74> lt Zeichen, die bei der Nachsendung "
" von Reports Probleme bereiten k<> nnen. Bitte w<> hle ein neues "
2002-03-10 11:09:16 +01:00
" Passwort, bevorzugt nur aus Buchstaben und Zahlen bestehend. " ) ) ;
2002-03-09 16:16:35 +01:00
}
f = f - > next ;
}
return 0 ;
}
2002-03-03 12:56:13 +01:00
static int
fix_seeds ( void )
{
region * r ;
for ( r = regions ; r ; r = r - > next ) {
if ( rtrees ( r , 0 ) > 25 & & rtrees ( r , 0 ) > rtrees ( r , 2 ) / 2 ) {
rsettrees ( r , 0 , rtrees ( r , 2 ) / 2 ) ;
}
}
return 0 ;
}
2002-04-21 19:44:17 +02:00
static int
guard_conversion ( void )
{
faction * f ;
unit * u ;
int mask = GUARD_CREWS | GUARD_LANDING | GUARD_TRAVELTHRU | GUARD_TAX ;
for ( f = factions ; f ; f = f - > next ) {
for ( u = f - > units ; u ; u = u - > nextF ) {
int g = getguard ( u ) ;
if ( ( g & mask ) = = mask ) {
setguard ( u , g | GUARD_PRODUCE | GUARD_RECRUIT ) ;
}
}
}
return 0 ;
}
2002-04-27 16:25:35 +02:00
static int
questportal_init ( void )
{
region * r1 = findregion ( 43 , - 39 ) ;
region * r2 = findregion ( 44 , - 39 ) ;
border * bo ;
unit * u ;
if ( r1 = = NULL | | r2 = = NULL ) return 0 ;
bo = new_border ( & bt_questportal , r1 , r2 ) ;
bo - > data = ( void * ) 3 ;
u = findunit ( atoi36 ( " L0sc " ) ) ;
if ( u ) i_change ( & u - > items , & it_questkey1 , 1 ) ;
2002-05-02 23:19:45 +02:00
2002-04-27 16:25:35 +02:00
u = findunit ( atoi36 ( " xi7m " ) ) ;
if ( u ) i_change ( & u - > items , & it_questkey2 , 1 ) ;
return 0 ;
}
2002-04-27 21:40:31 +02:00
static int
xe_init ( void )
{
faction * f = findfaction ( atoi36 ( " a5q " ) ) ;
if ( f ) {
a_add ( & f - > attribs , a_new ( & at_xontormiaexpress ) ) ;
}
return 0 ;
}
2002-05-05 10:06:19 +02:00
static int
fix_restart_flag ( void )
{
faction * f ;
for ( f = factions ; f ; f = f - > next ) {
freset ( f , FFL_RESTART ) ;
}
return 0 ;
}
2002-04-28 17:37:48 +02:00
extern border * borders [ ] ;
static void
fix_road_borders ( void )
{
border * delete [ 10000 ] ;
int hash ;
int i = 0 ;
for ( hash = 0 ; hash < BMAXHASH ; hash + + ) {
border * b ;
for ( b = borders [ hash ] ; b ; b = b - > next ) {
if ( b - > type = = & bt_road ) {
int x1 , x2 , y1 , y2 ;
region * r1 , * r2 ;
x1 = b - > from - > x ;
y1 = b - > from - > y ;
x2 = b - > to - > x ;
y2 = b - > to - > y ;
r1 = findregion ( x1 , y1 ) ;
r2 = findregion ( x2 , y2 ) ;
if ( r1 - > land = = NULL | | r2 - > land = = NULL
| | terrain [ r1 - > terrain ] . roadreq = = 0
| | terrain [ r2 - > terrain ] . roadreq = = 0 ) {
delete [ i ] = b ;
i + + ;
}
}
}
}
while ( i > 0 ) {
i - - ;
erase_border ( delete [ i ] ) ;
}
}
2001-01-25 10:37:55 +01:00
void
korrektur ( void )
{
2001-04-16 16:34:19 +02:00
# if TEST_LOCALES
setup_locales ( ) ;
2002-02-03 03:36:12 +01:00
# endif
2002-01-28 01:25:32 +01:00
fix_astralplane ( ) ;
2001-09-05 21:40:40 +02:00
fix_firewalls ( ) ;
2001-12-10 01:13:39 +01:00
fix_gates ( ) ;
2001-01-31 00:16:17 +01:00
# ifdef TEST_GM_COMMANDS
setup_gm_faction ( ) ;
# endif
2001-05-11 22:19:22 +02:00
update_gms ( ) ;
2001-02-13 00:06:44 +01:00
verify_owners ( false ) ;
2001-01-25 10:37:55 +01:00
/* fix_herbtypes(); */
# ifdef CONVERT_TRIGGER
2001-02-20 23:54:05 +01:00
convert_triggers ( ) ;
2001-01-25 10:37:55 +01:00
# endif
fix_migrants ( ) ;
2001-12-10 01:13:39 +01:00
no_teurefremde ( 1 ) ;
2001-09-05 21:40:40 +02:00
update_igjarjuk_quest ( ) ;
2001-01-25 10:37:55 +01:00
fix_allies ( ) ;
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
update_gmquests ( ) ; /* test gm quests */
2001-12-10 01:13:39 +01:00
/* fix_unitrefs(); */
2001-01-25 10:37:55 +01:00
stats ( ) ;
2002-05-02 23:19:45 +02:00
do_once ( " pers " , convert_orders ( ) ) ;
2001-12-10 01:13:39 +01:00
do_once ( " sql2 " , dump_sql ( ) ) ;
2002-04-21 13:39:47 +02:00
do_once ( " fw02 " , fix_watchers ( ) ) ;
2002-05-01 21:44:28 +02:00
do_once ( " fxh3 " , fix_plainherbs ( ) ) ;
2001-12-15 13:26:04 +01:00
# if NEW_RESOURCEGROWTH
2001-12-10 01:13:39 +01:00
/* do not remove do_once calls - old datafiles need them! */
do_once ( " rgrw " , convert_resources ( ) ) ;
do_once ( " rsfx " , read_resfix ( ) ) ;
# endif
/* do_once("xepl", create_xe()); */
2001-12-15 13:26:04 +01:00
# if GROWING_TREES
2001-12-10 01:13:39 +01:00
do_once ( " grtr " , growing_trees ( ) ) ;
2001-09-05 21:40:40 +02:00
# endif
2002-01-28 02:55:31 +01:00
do_once ( " fgms " , fix_gms ( ) ) ;
2001-12-15 13:26:04 +01:00
# if NEW_RESOURCEGROWTH
2001-12-10 01:13:39 +01:00
do_once ( " rndr " , randomized_resources ( ) ) ;
2001-12-15 13:26:04 +01:00
# endif
2001-12-23 10:23:53 +01:00
do_once ( " idlo " , fix_idleout ( ) ) ;
2002-01-13 08:59:41 +01:00
do_once ( " szip " , set_zip ( ) ) ;
2002-01-20 11:26:38 +01:00
do_once ( " heal " , heal_all ( ) ) ;
2002-02-17 13:15:39 +01:00
do_once ( " fquc " , fix_questcoors ( ) ) ;
2002-03-03 12:56:13 +01:00
do_once ( " fsee " , fix_seeds ( ) ) ;
2002-03-09 16:16:35 +01:00
do_once ( " orc2 " , orc_conversion2 ( ) ) ;
2002-03-10 11:09:16 +01:00
do_once ( " witm " , warn_items ( ) ) ;
2002-04-21 19:44:17 +02:00
do_once ( " guac " , guard_conversion ( ) ) ;
2002-04-27 16:25:35 +02:00
do_once ( " qpoi " , questportal_init ( ) ) ;
2002-04-27 21:40:31 +02:00
do_once ( " xini " , xe_init ( ) ) ;
2002-05-05 10:06:19 +02:00
do_once ( " rest " , fix_restart_flag ( ) ) ;
2002-03-09 16:16:35 +01:00
warn_password ( ) ;
2002-04-28 17:37:48 +02:00
fix_road_borders ( ) ;
2001-09-05 21:40:40 +02:00
2002-05-02 23:19:45 +02:00
/* seems something fishy is going on, do this just
* to be on the safe side :
2002-02-06 09:06:02 +01:00
*/
fix_demand ( ) ;
2001-09-05 21:40:40 +02:00
/* trade_orders(); */
2001-01-25 10:37:55 +01:00
if ( global . data_version < NEWROAD_VERSION ) {
newroads ( ) ;
}
/* immer ausf<73> hren, wenn neue Spr<70> che dazugekommen sind, oder sich
* Beschreibungen ge <EFBFBD> ndert haben */
show_newspells ( ) ;
fix_age ( ) ;
/* Immer ausf<73> hren! Erschafft neue Teleport-Regionen, wenn n<> tig */
create_teleport_plane ( ) ;
if ( global . data_version < TYPES_VERSION ) fix_icastles ( ) ;
2001-12-30 09:24:05 +01:00
# ifdef XMAS2000
2001-01-25 10:37:55 +01:00
santa_comes_to_town ( ) ;
# endif
# ifdef FUZZY_BASE36
enable_fuzzy = true ;
# endif
}
2001-02-09 20:52:59 +01:00
2001-01-25 10:37:55 +01:00
void
korrektur_end ( void )
{
/* fix_balsamfiasko(); */
2001-12-30 09:24:05 +01:00
# ifdef XMAS2001
do_once ( " 2001 " , xmas2001 ( ) ) ;
# endif
2002-02-03 09:29:28 +01:00
# if PEASANT_ADJUSTMENT == 1
do_once ( " peas " , peasant_adjustment ( ) ) ;
2002-02-10 18:56:03 +01:00
do_once ( " orcc " , orc_conversion ( ) ) ;
2002-02-03 09:29:28 +01:00
# endif
2001-01-25 10:37:55 +01:00
}
void
init_conversion ( void )
{
# if defined(CONVERT_TRIGGER)
at_register ( & at_relation ) ;
at_register ( & at_relbackref ) ;
at_register ( & at_trigger ) ;
at_register ( & at_action ) ;
# endif
}