dnl ====================================================================== dnl File : macros.m4 dnl Purpose : m4-macros fuer bg2-script-m4-sources dnl ====================================================================== divert(-1) define(`VAR_PREFIX',rs)dnl prefix for bgscript variables dnl -------------------- define(`WIDTH',`70')dnl define(`INDENT',`2')dnl define(`CMTSTART',// )dnl define(`NL',$1 )dnl newline define(`CMTLEN',`len(CMTSTART)')dnl dnl -------------------- define(`CAT',`ifelse($#,0,,$#,1,`$1',$#,2,`$1$2',`CAT(`$1',`CAT(`shift($@)')')')')dnl concat sth define(`REP',`ifelse($1,0,,$1,1,`$2',$1,2,`$2$2',eval($1%2),1,`CAT(`$2',REP(decr($1),`$2'))',`REP(2,REP(eval($1/2),`$2'))')')dnl repeat sth dnl -------------------- define(`IND',`CAT(`REP(eval(INDENT*$1),` ')',`$2')')dnl indent sth define(`CMT',`ifelse($#,2,`CAT(CMTSTART,IND($1,$2))',`CAT(NL(CMT($1,$2)),CMT($1,shift(shift($@))))')')dnl indented multiline comment dnl -------------------- define(`MAKELINE',`REP(eval(WIDTH/len(`$1')),`$1')')dnl a simple commented line define(`LINE1',`CMT(0,MAKELINE(`_'),)')dnl different styles define(`LINE2',`CMT(0,MAKELINE(`='))')dnl define(`LINE3',`CMT(0,MAKELINE(`-'))')dnl define(`LINE',`ifelse($1,1,`LINE1',$1,2,`LINE2',`LINE3')')dnl define(`SECTION',`NL(LINE($1))CMT(1,shift($@))')dnl a section (line+text) dnl -------------------- macros for flow-text: define(`BREAK',`patsubst($1,` ',`,')')dnl define(`UNBREAK',`ifelse($#,1,,$#,2,`$2',$#,3,`$2 $3',eval(len($2)>=$1),1,`$2,UNBREAK($1,shift(shift($@)))',`UNBREAK($1,`$2 $3',shift(shift(shift($@))))')')dnl define(`CMTFLOW',`CMT($1,UNBREAK(eval(WIDTH-10-$1*INDENT-CMTLEN),BREAK(shift($@))),)')dnl dnl you cannot use kommas in CMTFLOW dnl -------------------- define(`forloop', `pushdef(`$1', `$2')_forloop(`$1', `$2', `$3', `$4')popdef(`$1')') define(`_forloop', `$4`'ifelse($1, `$3', , `define(`$1', incr($1))_forloop(`$1', `$2', `$3', `$4')')')define(`x',`') dnl ====================================================================== dnl macros for code (basic IF THEN END, conditions, actions) define(`XX',`$@') define(`INDENTED',`ifelse($#<2,1,,$#,2,`IND($1,$2) ',`CAT(`IND($1,$2) ',INDENTED($1,shift(shift($*))))')') define(`TOK',`$*') define(`UND',`TOK($@)') define(`OR_INT',`OR($#) INDENTED(2,$*) //ENDOR') define(`ODER',`OR_INT(TOK($@))') define(`COND',`NL(IF)INDENTED(1,UND($@))NL(THEN)') define(`RESP',`IND(1,``RESPONSE #'')$1 ') define(`ACTIONS',`TOK($@)') define(`ACTION',`RESP(100)INDENTED(2,ACTIONS($@))XX(END) ') dnl ------ action blocks: define(`FORCE',`COND(`$1')ACTION(shift($@))') define(`ADDIT',`COND(`$1')ACTION(shift($@),Continue())') define(`ALLOW',`FORCE(`UND(`ActionListEmpty()',`$1')',shift($@))') define(`MAYADD',`ADDIT(`UND(ActionListEmpty(),`$1')',shift($@))') dnl ------ set/query variables: define(`varname',XX(VAR_PREFIX)XX($1)) define(`lvar',``"'varname(CAT(L_,$1))`"',"LOCALS"') define(`gvar',``"'varname(CAT(G_,$1))`"',"GLOBAL"') define(`lset',`SetGlobal(lvar($1),$2)') define(`leq',`Global(lvar($1),$2)') define(`lgt',`GlobalGT(lvar($1),$2)') define(`llt',`GlobalLT(lvar($1),$2)') define(`gset',`SetGlobal(gvar($1),$2)') define(`geq',`Global(gvar($1),$2)') define(`ggt',`GlobalGT(gvar($1),$2)') define(`glt',`GlobalLT(gvar($1),$2)') dnl -------- messages define(`STR_FOLLOW_MODE_ON',`835') define(`STR_FOLLOW_MODE_OFF',`836') define(`STR_SHOUT_HELP_NO',`830') define(`STR_SHOUT_HELP_75',`831') define(`STR_SHOUT_HELP_50',`832') define(`STR_SHOUT_HELP_25',`833') define(`STR_STOP',`15924') define(`STR_OFF',`16470') define(`STR_TARGET',`10070') define(`STR_HEALED',`14022') define(`STR_HEALING',`14178') define(`STR_CURE_LIGHT_WOUNDS',`12110') define(`STR_CURE_MEDIUM_WOUNDS',`3350') define(`STR_CURE_SERIOUS_WOUNDS',`12114') define(`STR_CURE_CRITICAL_WOUNDS',`12116') define(`STR_HEAL',`1453') dnl used DebugStringHead instead of DisplayStringHead and un/comment the next lines dnl define(`DebugStringHead',`') define(`DebugStringHead',`,DisplayStringHead($1,$2)') dnl DebugStringHead(object,str_id) dnl -------- Timers/Timeouts define(`TIMEOUT_ACK_STD',`3') define(`TIMEOUT_ACK_HEAL',TIMEOUT_ACK_STD) define(`TIMEOUT_ACK_UNPOISON',TIMEOUT_ACK_STD) define(`TIMEOUT_WAIT_HELP',5) define(`TIMEOUT_SPREAD',`15') define(`TIMER_ACK_HEAL',`1000') define(`TIMER_ACK_UNPOISON',`1001') define(`TIMER_SPREAD',`1002') define(`TIMER_WAIT_HELP',`1003') define(`START_TIMER',`StartTimer(TIMER_$1,TIMEOUT_$1)') dnl START_TIMER(what) define(`TIMEOUT',`TimerExpired(TIMER_$1)') dnl TIMEOUT(what) dnl -------- Orders define(`ORDER_REQ_HEAL',`2000') define(`ORDER_REQ_UNPOISON',`2001') define(`ORDER_ACK_HEAL',`2002') define(`ORDER_ACK_UNPOISON',`2003') define(`REQUEST',`GiveOrder($1,CAT(ORDER_REQ_,$2)),START_TIMER(CAT(ACK_,$2))') dnl REQUEST(from,what) define(`ACKNOWLEDGE',`GiveOrder($1,CAT(ORDER_ACK_,$2))') dnl ACKNOWLEDGE(who,what) define(`GOT_REQUEST',`ReceivedOrder([PC],CAT(ORDER_REQ_,$1))') dnl GOT_REQUEST(what) define(`GOT_ACKNOWLEDGE',`ReceivedOrder([PC],CAT(ORDER_ACK_,$1))') dnl GOT_ACK(what) dnl -------- who am i? define(`I_AM_THIEF',`ODER(Class(Myself,THIEF),Class(Myself,FIGHTER_THIEF),Class(Myself,MAGE_THIEF))') dnl -------- states define(`PANIC',StateCheck($1,STATE_PANIC)) define(`INVISIBLE',StateCheck($1,STATE_INVISIBLE)) define(`I_AM_POISONED',`ODER(HitBy([ANYONE],POISON),StateCheck(Myself,STATE_POISONED))')dnl true if i am POISONED define(`I_AM_NOT_POISONED',`UND(!HitBy([ANYONE],POISON),!StateCheck(Myself,STATE_POISONED))')dnl true if i am not POISONED define(`NO_ENEMY',`!See([ENEMY])') define(`SEE_ENEMY',`See([ENEMY])') dnl -------- using spells/items define(`USE_SPELL_ON_IF',`ALLOW(`UND($1,HaveSpell($3))',Spell($2,$3))')dnl USE_SPELL_ON_IF(condition,target,spell) define(`HAVE_ITEM',`HasItem($1,Myself)')dnl HAVE_ITEM(item) define(`USE_ITEM',`UseItem($1,Myself)')dnl USE_ITEM(item) define(`USE_ITEM_IF',`ALLOW(`UND($1,HAVE_ITEM($2))',USE_ITEM($2))')dnl USE_ITEM_IF(condition,item) define(`USE_SPELL_IF',`USE_SPELL_ON_IF(`$1',Myself,$2)')dnl USE_SPELL_IF(condition,spell) dnl -------- poison define(`HEARD_POISONED',`Heard([PC],POISONED)')dnl true if someone is POISONED dnl define(`HEALING_NEEDED',`UND(!leq(PainTolerance,0),)')dnl true if myself need help dnl -------- healing dnl HealState [UnpoisonState] dnl == 0 -> I'm ok dnl == 1 -> I spoke HURT [POISONED] dnl == 2 -> Someone said CAN_HEAL [CAN_UNPOISON] (I gave order ORDER_HEAL_ME [ORDER_UNPOISON_ME]) dnl define(`HEARD_HURT',`Heard([PC],HURT)')dnl define(`HEALTH_BELOW',`HPPercentLT(Myself,$1)')dnl true if my healthpoints are below $1 define(`HEALTH_IN_RANGE',`UND(HPPercentGT(Myself,eval($1-1)),HPPercentLT(Myself,eval($2+1)))')dnl HEALTH_IN_RANGE(low,high) dnl define(`NEED_HELP1',`UND(SEE_ENEMY,leq(PainTolerance,1),leq(HealState,0),HEALTH_IN_RANGE(1,24))')dnl dnl define(`NEED_HELP2',`UND(SEE_ENEMY,leq(PainTolerance,2),leq(HealState,0),HEALTH_IN_RANGE(25,49))')dnl dnl define(`NEED_HELP3',`UND(SEE_ENEMY,leq(PainTolerance,3),leq(HealState,0),HEALTH_IN_RANGE(50,74))')dnl define(`NEED_HELP1',`UND(leq(PainTolerance,1),leq(HealState,0),HEALTH_IN_RANGE(1,24))')dnl define(`NEED_HELP2',`UND(leq(PainTolerance,2),leq(HealState,0),HEALTH_IN_RANGE(1,49))')dnl define(`NEED_HELP3',`UND(leq(PainTolerance,3),leq(HealState,0),HEALTH_IN_RANGE(1,74))')dnl dnl -------- leader define(`SetAsLeader', `FORCE( `UND(HotKey(C),InPartySlot(Myself,$1),!geq(FollowMe,eval($1+1)))', DisplayStringHead(Myself,STR_FOLLOW_MODE_ON), gset(FollowMe,eval($1+1)))' )dnl SetAsLeader(playernumber) define(`FollowLeader',`FORCE(`UND(leq(AutoFollow,1),geq(FollowMe,$1),!Range(Player$1,20), !OnScreen(Myself),!InPartySlot(Myself,eval($1-1)))', MoveToObject(Player$1))')dnl FOLLOW(playernumber) dnl -------- autocenter dnl --- not usable :( define(`SetCenterOn', `FORCE( `UND(HotKey(U),InPartySlot(Myself,$1),!geq(CenterMe,eval($1+1)))', gset(CenterMe,eval($1+1)))' )dnl SetCenterOn(playernumber) define(`SetCenterOff', `FORCE( `UND(HotKey(U),InPartySlot(Myself,$1),geq(CenterMe,eval($1+1)))', gset(CenterMe,99))' )dnl SetCenterOff(playernumber) define(`CenterOn', `FORCE( `UND(InPartySlot(Myself,$1),geq(CenterMe,eval($1+1)))', MoveViewObject(Myself,0))' )dnl CenterOn(playernumber) dnl -------- melee/ranged define(`Melee',`EquipMostDamagingMelee()') define(`Ranged',`EquipRanged()') define(`I_AM_MELEE',`leq(MeleeAttack,1)') define(`I_AM_RANGED',`leq(MeleeAttack,0)') dnl -------- Distances define(`D_VERY_NEAR',`3') define(`D_NEAR',`6') define(`D_MEDIUM',`10') define(`D_FAR',`15') define(`D_VERY_FAR',`25') define(`DIST_VERY_NEAR',`Range($1,D_VERY_NEAR)') define(`DIST_NEAR',`Range($1,D_NEAR)') define(`DIST_MEDIUM',`Range($1,D_MEDIUM)') define(`DIST_FAR',`Range($1,D_FAR)') define(`DIST_VERY_FAR',`!DIST_FAR($1)') dnl -------- movement define(`MEET_WITH',`MoveToObject($1)')dnl define(`RUN_AWAY_FROM',`RunAwayFrom($1,30)') dnl in 1/15 sec define(`KEEP_DISTANCE_TO',RunAwayFrom($1,15)) dnl in 1/15 sec define(`GOTO_SAFE_POSITION',`RUN_AWAY_FROM($1)') dnl -------- attackers define(`NEAREST_ENEMY',`NearestEnemyOf(Myself)') define(`IS_VALUABLE_TARGET',`UND(!PANIC($1),Exists($1),!InParty($1))') define(`I_AM_ATTACKED',AttackedBy([ANYONE],DEFAULT)) define(`ATTACKER',LastAttackerOf(Myself))dnl you have to use I_AM_ATTACKED or ATTACKED before define(`ATTACKED',`UND(I_AM_ATTACKED,IS_VALUABLE_TARGET(ATTACKER))') define(`HIS_ATTACKER',LastAttackerOf(LastHeardBy(Myself)))dnl you have to use FRIEND_ATTACKED before define(`HIS_TARGET',NearestEnemyOf(LastHeardBy(Myself)))dnl you have to use FRIEND_ATTACKING before define(`FRIEND_ATTACKED',`UND(Heard([PC],UNDER_ATTACK),IS_VALUABLE_TARGET(HIS_ATTACKER))') define(`FRIEND_ATTACKING',`UND(Heard([PC],ATTACKING),IS_VALUABLE_TARGET(HIS_TARGET))') define(`LAST_SEEN',`LastSeenBy(Myself)') define(`SEE_TARGET',`UND(See($1EnemyOf(Myself)),IS_VALUABLE_TARGET(LAST_SEEN))') define(`ATTACK',`Attack($1)') dnl define(`ATTACK',`AttackOneRound($1)') dnl seems to create less attacks define(`x',`') dnl -------- divert(0)dnl