#include <thing/properties.h>#include <wizlevels.h>#include <new_skills.h>#include <spellbook.h>
gehe zum Quellcode dieser Datei
Makrodefinitionen | |
| #define | ME this_object() |
| #define | SMUL(x, y) ((x<0 && y<0)?(-1*x*y):(x*y)) |
Funktionen | |
| void | create () |
| mapping | _query_sb_spells () |
| mapping | QuerySpell (string spell) |
| varargs int | AddSpell (string verb, int kosten, mixed ski) |
| int | TryAttackSpell (object victim, int damage, mixed dtypes, mixed is_spell, object caster, mapping sinfo) |
| varargs int | TryDefaultAttackSpell (object victim, object caster, mapping sinfo, mixed si_spell) |
| int | SpellSuccess (object caster, mapping sinfo) |
| int | CanTrySpell (object caster, mapping sinfo) |
| void | Learn (object caster, string spell, mapping sinfo) |
| void | Erfolg (object caster, string spell, mapping sinfo) |
| void | Misserfolg (object caster, string spell, mapping sinfo) |
| string | SelectSpell (string spell, mapping sinfo) |
| varargs void | prepare_spell (object caster, string spell, mapping sinfo) |
| varargs int | UseSpell (object caster, string spell, mapping sinfo) |
| object * | FindGroup (object pl, int who) |
| object * | FindGroupN (object pl, int who, int n) |
| object * | FindGroupP (object pl, int who, int pr) |
| varargs mixed | FindDistantGroups (object pl, int dist, int dy, int dx) |
| varargs object * | FindDistantGroup (object pl, int who, int dist, int dy, int dx) |
| static varargs object | find_victim (string wen, object pl) |
| varargs object | FindVictim (string wen, object pl, string msg) |
| varargs object | FindLivingVictim (string wen, object pl, string msg) |
| static private varargs object | DoFindEnemyVictim (string wen, object pl, string msg, mixed func, int min, int max) |
| varargs object | FindEnemyVictim (string wen, object pl, string msg) |
| varargs object | FindNearEnemyVictim (string wen, object pl, string msg) |
| varargs object | FindFarEnemyVictim (string wen, object pl, string msg, int min, int max) |
| varargs object | FindDistantEnemyVictim (string wen, object pl, string msg, int dist, int dy) |
| varargs int | TryGlobalAttackSpell (object caster, mapping sinfo, int suc, int damage, mixed dt, mixed is_spell, int dist, int depth, int width) |
Variablen | |
| inherit std | thing |
| inherit std | restriction_checker |
| inherit std player | pklog |
| #define ME this_object() |
Definiert in Zeile 23 der Datei spellbook.c.
| mapping _query_sb_spells | ( | ) |
Definiert in Zeile 34 der Datei spellbook.c.
Benutzt F_VALUE, P_SB_SPELLS und Query().
00034 { 00035 // Kopie liefern, da sonst versehentlich schnell eine Aenderung des 00036 // originalen Mappings hier passieren kann. 00037 return(deep_copy(Query(P_SB_SPELLS, F_VALUE))); 00038 }

| varargs int AddSpell | ( | string | verb, | |
| int | kosten, | |||
| mixed | ski | |||
| ) |
Definiert in Zeile 53 der Datei spellbook.c.
Benutzt AddSkillMappings(), F_VALUE, level, P_GLOBAL_SKILLPROPS, P_LEVEL, P_SB_SPELLS, Query(), QueryProp(), SetProp(), SI_SKILLRESTR_LEARN, SI_SPELL, SI_SPELLCOST und SP_NAME.
00053 { 00054 int level; 00055 mapping spells; 00056 00057 if (!verb || kosten<0) 00058 return 0; 00059 00060 verb=lower_case(verb); 00061 level=(intp(ski))?ski:0; 00062 00063 if (!mappingp(ski)) ski=([]); 00064 // Zur Sicherheit eine Kopie machen, wer weiss, was da uebergeben wird, bzw. 00065 // was der Setzende mit ski hinterher noch macht. 00066 else ski=deep_copy(ski); 00067 00068 ski=AddSkillMappings(QueryProp(P_GLOBAL_SKILLPROPS),ski); 00069 ski+=([SI_SPELLCOST:kosten]); 00070 // SI_SPELL-Submapping hinzufuegen, wenn nicht da. 00071 if (!member(ski,SI_SPELL)) 00072 ski+=([SI_SPELL:([]) ]); 00073 // gleiches SP_NAME in Skillmapping und SI_SPELL-Mapping eintragen. *seufz* 00074 // Noetig, weil es in der Vergangenheit offenbar eine grosse Verwirrung 00075 // gegeben hat, wo SP_NAME hingehoert (in SI_SPELL) und min. das halbe Mud 00076 // falsch prueft. TODO: Wenn der Rest vom mud richtig prueft, sollte 00077 // sichergestellt werden, dass SP_NAME nur noch in SI_SPELL drinsteht. 00078 if (!stringp(ski[SP_NAME]) && !stringp(ski[SI_SPELL][SP_NAME])) { 00079 ski[SP_NAME] = verb; 00080 ski[SI_SPELL][SP_NAME] = verb; 00081 } 00082 else if (stringp(ski[SP_NAME]) && !stringp(ski[SI_SPELL][SP_NAME]) ) 00083 ski[SI_SPELL][SP_NAME] = ski[SP_NAME]; 00084 else if (stringp(ski[SI_SPELL][SP_NAME]) && !stringp(ski[SP_NAME]) ) 00085 ski[SP_NAME] = ski[SI_SPELL][SP_NAME]; 00086 00087 if (level) 00088 ski=AddSkillMappings(ski,([SI_SKILLRESTR_LEARN:([P_LEVEL:level])])); 00089 00090 // Abfrage per Query(), um das Mapping als Referenz, nicht als Kopie zu 00091 // bekommen, das spart etwas Zeit. 00092 if (!(spells=Query(P_SB_SPELLS,F_VALUE))) { 00093 spells=([]); 00094 SetProp(P_SB_SPELLS,spells); 00095 } 00096 // Spell setzen... 00097 spells[verb]=ski; 00098 // Set() nicht noetig, da Query() an spell das Originalmapping geliefert hat 00099 // und dieses bereits jetzt geaendert wurde. ;-) 00100 //Set(P_SB_SPELLS,spells+([verb:ski]),F_VALUE); 00101 00102 // hat wohl geklappt... 00103 return(1); 00104 }

| int CanTrySpell | ( | object | caster, | |
| mapping | sinfo | |||
| ) |
Definiert in Zeile 191 der Datei spellbook.c.
Benutzt check_restrictions(), P_GHOST und SI_SKILLRESTR_USE.
Wird benutzt von UseSpell().
00191 { 00192 mapping rmap; 00193 string res; 00194 00195 if (caster->QueryProp(P_GHOST)) { 00196 write("Als Geist kannst Du nicht zaubern.\n"); 00197 return 0; 00198 } 00199 if ((rmap=sinfo[SI_SKILLRESTR_USE]) 00200 && (res=check_restrictions(caster,rmap))) { 00201 write(res); 00202 return 0; 00203 } 00204 return 1; 00205 }


| void create | ( | ) |
Definiert in Zeile 25 der Datei spellbook.c.
Benutzt create(), F_MODE_AS, F_VALUE, P_SB_SPELLS, PROTECTED und Set().
00025 { 00026 seteuid(getuid()); 00027 // diese Prop sollte von aussen nicht direkt geaendert werden koennen. 00028 Set(P_SB_SPELLS,([]),F_VALUE); 00029 Set(P_SB_SPELLS,PROTECTED,F_MODE_AS); 00030 00031 ::create(); 00032 }

| static private varargs object DoFindEnemyVictim | ( | string | wen, | |
| object | pl, | |||
| string | msg, | |||
| mixed | func, | |||
| int | min, | |||
| int | max | |||
| ) | [static] |
Definiert in Zeile 596 der Datei spellbook.c.
Benutzt FindLivingVictim(), no_attack(), P_NO_ATTACK und WER.
Wird benutzt von FindDistantEnemyVictim(), FindEnemyVictim(), FindFarEnemyVictim() und FindNearEnemyVictim().
00597 { 00598 object vic; 00599 mixed no_attack; 00600 int row; 00601 00602 if (!(vic=FindLivingVictim(wen,pl,msg))) { 00603 if ((stringp(wen) && wen!="") || !objectp(pl)) 00604 return 0; 00605 if (pointerp(func)) { // Soll einer DIESER Gegner genommen werden? 00606 if (!(vic=(object)pl->SelectEnemy(func))) // Dann daraus auswaehlen 00607 return 0; 00608 } else { 00609 if (!stringp(func)) 00610 func="SelectEnemy"; 00611 if (!(vic=(object)call_other(pl,func,0,min,max))) 00612 return 0; 00613 } 00614 func=0; // kein zweites Mal pruefen. 00615 } 00616 if (no_attack = (mixed)vic->QueryProp(P_NO_ATTACK)) { 00617 if (stringp(no_attack)) 00618 write(no_attack); 00619 else 00620 write(vic->Name(WER,1)+" laesst sich nicht angreifen.\n"); 00621 return 0; 00622 } 00623 if (vic==pl) { 00624 write("Du koenntest Dir dabei wehtun.\n"); 00625 return 0; 00626 } 00627 if (stringp(func)) { 00628 switch(func) { 00629 case "SelectNearEnemy": 00630 if (pl->PresentPosition()>1) { 00631 write("Du stehst nicht in der ersten Kampfreihe.\n"); 00632 return 0; 00633 } 00634 if (vic->PresentPosition()>1) { 00635 write(vic->Name(WER,1)+" ist in einer hinteren Kampfreihe.\n"); 00636 return 0; 00637 } 00638 break; 00639 case "SelectFarEnemy": 00640 if (row=(int)vic->PresentPosition()) 00641 row--; 00642 if (row>=min && row<=max) 00643 break; 00644 if (row<min) 00645 write(vic->Name(WER,1)+" ist zu nahe.\n"); 00646 else if (row>max) 00647 write(vic->Name(WER,1)+" ist zu weit weg.\n"); 00648 else 00649 write(vic->Name(WER,1)+" ist unerreichbar.\n"); 00650 return 0; 00651 default:; 00652 } 00653 } else if (pointerp(func)) { 00654 if (member(func,vic)<0) { 00655 write(vic->Name(WER,1)+" ist unerreichbar.\n"); 00656 return 0; 00657 } 00658 } 00659 00660 if (!pl->IsEnemy(vic)) // War es bisher kein Feind? 00661 pl->Kill(vic); // Dann ist es jetzt einer. 00662 return vic; 00663 }


| void Erfolg | ( | object | caster, | |
| string | spell, | |||
| mapping | sinfo | |||
| ) |
Definiert in Zeile 240 der Datei spellbook.c.
Benutzt env().
Wird benutzt von UseSpell().
00240 { 00241 object env; 00242 if(env=environment(caster)) 00243 env->SpellInform(caster,spell,sinfo); 00244 }


| static varargs object find_victim | ( | string | wen, | |
| object | pl | |||
| ) | [static] |
Definiert in Zeile 557 der Datei spellbook.c.
Wird benutzt von FindVictim().
00557 { 00558 object victim; 00559 00560 if (!pl) return 0; 00561 if (!strlen(wen)) { 00562 if (victim = (object)pl->SelectEnemy()) 00563 return victim; 00564 else 00565 return 0; 00566 } 00567 if (victim = present(wen, environment(pl))) 00568 return victim; 00569 else if (victim = present(wen, pl)) 00570 return victim; 00571 else 00572 return 0; 00573 }

| varargs object FindDistantEnemyVictim | ( | string | wen, | |
| object | pl, | |||
| string | msg, | |||
| int | dist, | |||
| int | dy | |||
| ) |
Definiert in Zeile 682 der Datei spellbook.c.
Benutzt DoFindEnemyVictim() und FindDistantGroup().
00683 { 00684 return DoFindEnemyVictim(wen,pl,msg, 00685 FindDistantGroup(pl,-1,dist,dy,10000)); 00686 }

| varargs object* FindDistantGroup | ( | object | pl, | |
| int | who, | |||
| int | dist, | |||
| int | dy, | |||
| int | dx | |||
| ) |
Definiert in Zeile 544 der Datei spellbook.c.
Benutzt FindDistantGroups().
Wird benutzt von FindDistantEnemyVictim().
00544 { 00545 mixed *x; 00546 00547 x=FindDistantGroups(pl,dist,dy,dx); 00548 if (who<0) 00549 return x[0]; 00550 else if (who>0) 00551 return x[1]; 00552 return x[0]+x[1]; 00553 }


| varargs mixed FindDistantGroups | ( | object | pl, | |
| int | dist, | |||
| int | dy, | |||
| int | dx | |||
| ) |
Definiert in Zeile 445 der Datei spellbook.c.
Benutzt EMPTY_TEAMARRAY, i, IS_LEARNING, m_delete(), MAX_TEAM_ROWLEN, MAX_TEAMROWS, min, ob(), P_FRIEND, P_GHOST, P_NO_ATTACK, P_NO_GLOBAL_ATTACK, P_TEAM, qp, SA_EXTENSION, SA_RANGE und x.
Wird benutzt von FindDistantGroup() und TryGlobalAttackSpell().
00445 { 00446 mapping pos; 00447 object ob,enteam,myteam; 00448 int p1,min,max,i; 00449 mixed *b_rows,x; 00450 closure is_enemy, qp; 00451 00452 if (!objectp(pl) || !environment(pl)) 00453 return ({({}),({})}); 00454 if (!dy) dy=100; 00455 if (!dx) dx=MAX_TEAM_ROWLEN*100; 00456 x=(int)pl->QuerySkillAttribute(SA_EXTENSION); 00457 dx=(dx*x)/100;dy=(dy*x)/100; 00458 dist=(dist*(int)pl->QuerySkillAttribute(SA_RANGE))/100; 00459 min=dist-dy/2; 00460 max=dist+dy/2; 00461 00462 pos=([]); 00463 p1=query_once_interactive(pl) ? 1 : -1; 00464 is_enemy=symbol_function("IsEnemy",pl); // zur Beschleunigung 00465 myteam=(object)pl->QueryProp(P_TEAM); 00466 for (ob=first_inventory(environment(pl));ob;ob=next_inventory(ob)) { 00467 if (!living(ob)) continue; 00468 qp=symbol_function("QueryProp",ob); // zur Beschleunigung 00469 00470 // Zuerst mal die Position feststellen: 00471 if (!objectp(enteam=funcall(qp,P_TEAM))) 00472 pos[ob]=1; 00473 else if (!pos[ob] && mappingp(x=(mapping)ob->PresentTeamPositions())) 00474 pos+=x; 00475 // PresentTeamPositions wird nur einmal pro Team ausgerechnet, weil 00476 // anschliessend jedes anwesende Teammitglied pos[ob]!=0 hat. 00477 00478 pos[ob]=(2*pos[ob])-1; 00479 // Reihen sollen Abstand 2 haben, auch Reihen 1 und -1 (nach Umrechnung) 00480 00481 // Feindliche Reihen an Y-Achse spiegeln, also gegenueber hinstellen: 00482 if (funcall(is_enemy,ob)) 00483 pos[ob]*=-1; // Ist auf jeden Fall Feind 00484 else if (objectp(myteam) && myteam==enteam) 00485 ; // Teammitglieder sind immer auf eigener Seite 00486 else 00487 pos[ob]*=(p1*((int)(query_once_interactive(ob)|| 00488 funcall(qp,P_FRIEND))?1:-1)); 00489 00490 // Den Spieler auf keinen Fall entfernen 00491 if (ob==pl) 00492 continue; 00493 // Netztote, Geister und unsichtbare Magier nicht beruecksichtigen, 00494 // nicht (global) angreifbare Monster und nicht-feindliche Magier 00495 // von feindlicher Seite entfernen. 00496 if ((!interactive(ob) && query_once_interactive(ob)) // Netztote raus 00497 || funcall(qp,P_GHOST) 00498 || (IS_LEARNING(ob) && funcall(qp,P_INVIS)) // Bin nicht da :-) 00499 || (pos[ob]<0 && (funcall(qp,P_NO_GLOBAL_ATTACK) // Nicht angreifen 00500 || funcall(qp,P_NO_ATTACK) 00501 || (IS_LEARNING(ob) && !funcall(is_enemy,ob))))) 00502 efun::m_delete(pos,ob); 00503 } 00504 00505 // Reihen aufstellen 00506 // Kampfreihe: | 5 4 3 2 1 || 1 2 3 4 5| 00507 // Arrays: |0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19| 00508 // |<----------- Freunde ------->||<--------- Feinde -------->| 00509 b_rows=EMPTY_TEAMARRAY+EMPTY_TEAMARRAY+EMPTY_TEAMARRAY+EMPTY_TEAMARRAY; 00510 x=m_indices(pos); 00511 for (i=sizeof(x)-1;i>=0;i--) { 00512 p1=2*MAX_TEAMROWS-pos[ob=x[i]]; 00513 pos[ob]=p1; 00514 if (p1>=0 && p1<4*MAX_TEAMROWS) { 00515 if (random(100)<50) // Damit gut gemischt wird... 00516 b_rows[p1]=b_rows[p1]+({ob}); // zufaellig hinten anfuegen 00517 else 00518 b_rows[p1]=({ob})+b_rows[p1]; // oder vorne anfuegen. 00519 } 00520 } 00521 00522 // Umrechnung von Min, Max auf Reihen 00523 // ... -2: -124..-75, -1:-74..-25, 0:-24..24, 1:25..74 2:75..124 ... 00524 // Das muss man machen, wenn man keine vernuenftige Rundungsfunktion hat: 00525 if (min<0) min=-1*((25-min)/50); else min=(25+min)/50; 00526 if (max<0) max=-1*((25-max)/50); else max=(25+max)/50; 00527 // Relativ zur Position des Spielers verschieben: 00528 p1=pos[pl];min+=p1;max+=p1; 00529 // Umrechnung von Breite auf Anzahl: 00530 dx=((dx+50)/100)-1;if (dx<0) dx=0; 00531 00532 x=({({}),({})}); 00533 for (i=0;i<2*MAX_TEAMROWS;i++) 00534 if (i>=min && i<=max) 00535 x[1]+=b_rows[i][0..dx]; // Freunde 00536 for (i=2*MAX_TEAMROWS+1;i<4*MAX_TEAMROWS;i++) 00537 if (i>=min && i<=max) 00538 x[0]+=b_rows[i][0..dx]; // Feinde 00539 00540 return x; 00541 }


| varargs object FindEnemyVictim | ( | string | wen, | |
| object | pl, | |||
| string | msg | |||
| ) |
Definiert in Zeile 666 der Datei spellbook.c.
Benutzt DoFindEnemyVictim().
Wird benutzt von feuerball(), kampfschrei(), pfeil() und saeurestrahl().
00666 { 00667 return DoFindEnemyVictim(wen,pl,msg,"SelectEnemy"); 00668 }


| varargs object FindFarEnemyVictim | ( | string | wen, | |
| object | pl, | |||
| string | msg, | |||
| int | min, | |||
| int | max | |||
| ) |
Definiert in Zeile 676 der Datei spellbook.c.
Benutzt DoFindEnemyVictim().
00677 { 00678 return DoFindEnemyVictim(wen,pl,msg,"SelectFarEnemy",min,max); 00679 }

| object* FindGroup | ( | object | pl, | |
| int | who | |||
| ) |
Definiert in Zeile 387 der Datei spellbook.c.
Benutzt env(), IS_LEARNING, ob(), P_FRIEND, P_GHOST, P_NO_ATTACK, P_NO_GLOBAL_ATTACK, P_TEAM, qp und team.
Wird benutzt von FindGroupN() und FindGroupP().
00387 { 00388 object *res,ob,env,team; 00389 int p1,p2; 00390 closure qp; 00391 00392 res=({}); 00393 if (!pl || !(env=environment(pl))) return res; 00394 p1 = query_once_interactive(pl) ? 1 : -1; 00395 team=(object)pl->QueryProp(P_TEAM); 00396 for (ob=first_inventory(env);ob;ob=next_inventory(ob)) { 00397 if (!living(ob)) continue; 00398 qp=symbol_function("QueryProp",ob); 00399 if (pl->IsEnemy(ob)) // Feinde sind immer Gegner 00400 p2=-1*p1; 00401 else if (objectp(team) && funcall(qp,P_TEAM)==team) 00402 p2=p1; // Teammitglieder sind immer auf Seite des Spielers 00403 else 00404 p2 = (query_once_interactive(ob)||funcall(qp,P_FRIEND)) ? 1 : -1; 00405 if (p2>0 && !interactive(ob) && query_once_interactive(ob)) 00406 continue; // keine Netztoten. 00407 if (funcall(qp,P_GHOST)) 00408 continue; 00409 if ( who<0 && (funcall(qp,P_NO_ATTACK) || funcall(qp,P_NO_GLOBAL_ATTACK)) ) 00410 continue; 00411 if (IS_LEARNING(ob) && 00412 (funcall(qp,P_INVIS) || (who<0 && !pl->IsEnemy(ob)))) 00413 continue; 00414 if (p1*p2*who >=0) 00415 res+=({ob}); 00416 } 00417 return res; 00418 }


| object* FindGroupN | ( | object | pl, | |
| int | who, | |||
| int | n | |||
| ) |
Definiert in Zeile 421 der Datei spellbook.c.
Benutzt FindGroup() und SA_EXTENSION.
00421 { 00422 if (!pl) return ({}); 00423 n=(n*(int)pl->QuerySkillAttribute(SA_EXTENSION))/100; 00424 if (n<1) n=1; 00425 return FindGroup(pl,who)[0..(n-1)]; 00426 }

| object* FindGroupP | ( | object | pl, | |
| int | who, | |||
| int | pr | |||
| ) |
Definiert in Zeile 429 der Datei spellbook.c.
Benutzt FindGroup(), i und SA_EXTENSION.
00429 { 00430 object *res,*nres; 00431 int i; 00432 00433 nres=({}); 00434 if (!pl) return nres; 00435 pr=(pr*(int)pl->QuerySkillAttribute(SA_EXTENSION))/100; 00436 if (pr<0) return nres; 00437 res=FindGroup(pl,who); 00438 for (i=sizeof(res)-1;i>=0;i--) 00439 if (pr>=random(100)) 00440 nres+=({res[i]}); 00441 return nres; 00442 }

| varargs object FindLivingVictim | ( | string | wen, | |
| object | pl, | |||
| string | msg | |||
| ) |
Definiert in Zeile 583 der Datei spellbook.c.
Benutzt FindVictim() und P_GHOST.
Wird benutzt von DoFindEnemyVictim() und schaetz().
00583 { 00584 object vic; 00585 00586 if (!(vic=FindVictim(wen,pl,msg))) 00587 return 0; 00588 if (!living(vic) || vic->QueryProp(P_GHOST)) { 00589 printf("%s lebt doch nicht!\n", capitalize((string)vic->name())); 00590 return 0; 00591 } 00592 return vic; 00593 }


| varargs object FindNearEnemyVictim | ( | string | wen, | |
| object | pl, | |||
| string | msg | |||
| ) |
Definiert in Zeile 671 der Datei spellbook.c.
Benutzt DoFindEnemyVictim().
00671 { 00672 return DoFindEnemyVictim(wen,pl,msg,"SelectNearEnemy"); 00673 }

| varargs object FindVictim | ( | string | wen, | |
| object | pl, | |||
| string | msg | |||
| ) |
Definiert in Zeile 575 der Datei spellbook.c.
Benutzt find_victim().
Wird benutzt von FindLivingVictim() und identifiziere().
00575 { 00576 object vic; 00577 00578 if (!(vic=find_victim(wen,pl)) && msg) 00579 write(msg); 00580 return vic; 00581 }


| void Learn | ( | object | caster, | |
| string | spell, | |||
| mapping | sinfo | |||
| ) |
Definiert in Zeile 208 der Datei spellbook.c.
Benutzt A_CON, A_DEX, A_INT, A_STR, GetFValue(), GetFValueO(), GetOffset(), SI_DIFFICULTY, SI_LEARN_ATTRIBUTE, SI_SKILLLEARN und SI_SPELLCOST.
Wird benutzt von Misserfolg().
00208 { 00209 int val,diff,attval; 00210 mapping attr; 00211 00212 // Attribut sollte int sein, wenn nicht anders angegeben 00213 if (mappingp(sinfo[SI_LEARN_ATTRIBUTE])) 00214 { 00215 attr=sinfo[SI_LEARN_ATTRIBUTE]; 00216 // Direkt in einem durch berechnen. 00217 // Ich gehe davon aus, dass wir nie nie nie 00218 // ein weiteres Attribut ins MG einfuegen. 00219 // Wir berechnen den Mittelwert 00220 attval=((int)caster->QueryAttribute(A_INT)*attr[A_INT]+ 00221 (int)caster->QueryAttribute(A_DEX)*attr[A_DEX]+ 00222 (int)caster->QueryAttribute(A_STR)*attr[A_STR]+ 00223 (int)caster->QueryAttribute(A_CON)*attr[A_CON]) 00224 /(attr[A_CON]+attr[A_INT]+attr[A_STR]+attr[A_DEX]); 00225 00226 00227 } else { 00228 attval=(int)caster->QueryAttribute(A_INT); 00229 } 00230 00231 00232 val=((attval/2)*GetFValue(SI_SKILLLEARN,sinfo,caster)+ 00233 GetOffset(SI_SKILLLEARN,sinfo,caster)); 00234 if (!(diff=GetFValueO(SI_DIFFICULTY,sinfo,caster))) 00235 diff=GetFValueO(SI_SPELLCOST,sinfo,caster); 00236 caster->LearnSkill(spell,val,diff); 00237 }


| void Misserfolg | ( | object | caster, | |
| string | spell, | |||
| mapping | sinfo | |||
| ) |
Definiert in Zeile 247 der Datei spellbook.c.
Benutzt Learn().
Wird benutzt von UseSpell().
00247 { 00248 write("Der Zauberspruch ist missglueckt.\n"); 00249 write("Du lernst aus Deinem Fehler.\n"); 00250 Learn(caster,spell,sinfo); 00251 }


| varargs void prepare_spell | ( | object | caster, | |
| string | spell, | |||
| mapping | sinfo | |||
| ) |
Definiert in Zeile 261 der Datei spellbook.c.
Benutzt SI_PREPARE_MSG.
Wird benutzt von UseSpell().
00261 { 00262 string txt; 00263 00264 if (!caster || !spell) return ; 00265 if (!mappingp(sinfo) || !stringp(txt=sinfo[SI_PREPARE_MSG])) 00266 txt="Du bereitest Dich auf den Spruch ``%s'' vor.\n"; 00267 tell_object(caster,sprintf(txt,spell)); 00268 }

| mapping QuerySpell | ( | string | spell | ) |
Definiert in Zeile 40 der Datei spellbook.c.
Benutzt P_SB_SPELLS und Query().
00040 { 00041 mapping spi; 00042 00043 //Query-Methode umgehen, damit nur ein Spellmapping kopiert werden muss und 00044 //nicht das ganzen Mapping mit allen Spells. 00045 if (!spell 00046 || !(spi=Query(P_SB_SPELLS)) 00047 || !(spi=spi[spell])) 00048 return 0; 00049 return deep_copy(spi); 00050 }

| string SelectSpell | ( | string | spell, | |
| mapping | sinfo | |||
| ) |
Definiert in Zeile 254 der Datei spellbook.c.
Benutzt SI_SKILLFUNC.
Wird benutzt von UseSpell().
00254 { 00255 if (sinfo && sinfo[SI_SKILLFUNC]) 00256 return sinfo[SI_SKILLFUNC]; 00257 return spell; 00258 }

| int SpellSuccess | ( | object | caster, | |
| mapping | sinfo | |||
| ) |
Definiert in Zeile 179 der Datei spellbook.c.
Benutzt MAX_ABILITY, SI_SKILLABILITY, SK_CASTING und SMUL.
Wird benutzt von ausweichen(), feuerball(), identifiziere(), kampfschrei(), licht(), pfeil(), saeurestrahl(), schaetz() und schnell().
00179 { 00180 int cval,abil,res; 00181 00182 abil=sinfo[SI_SKILLABILITY]; 00183 cval=(int)caster->UseSkill(SK_CASTING); 00184 res=abil + (SMUL(abil,cval)) / MAX_ABILITY - random(MAX_ABILITY); 00185 if (cval && res>MAX_ABILITY) // besonders gut gelungen? 00186 caster->LearnSkill(SK_CASTING,1+(res-MAX_ABILITY)/2000); 00187 return res; 00188 }

| int TryAttackSpell | ( | object | victim, | |
| int | damage, | |||
| mixed | dtypes, | |||
| mixed | is_spell, | |||
| object | caster, | |||
| mapping | sinfo | |||
| ) |
Definiert in Zeile 107 der Datei spellbook.c.
Benutzt CheckPlayerAttack(), no_attack(), P_GHOST, P_NO_ATTACK, P_NOMAGIC, SA_DAMAGE, SA_ENEMY_SAVE, SI_NOMAGIC, SP_NAME und WER.
Wird benutzt von TryDefaultAttackSpell() und TryGlobalAttackSpell().
00108 { 00109 mixed no_attack; 00110 int nomag; 00111 00112 if (no_attack = (mixed)victim->QueryProp(P_NO_ATTACK)) { 00113 if (stringp(no_attack)) 00114 write(no_attack); 00115 else 00116 write(victim->Name(WER,1)+" laesst sich nicht angreifen!\n"); 00117 return 0; 00118 } 00119 if (victim->QueryProp(P_GHOST)) { 00120 write(victim->Name(WER,1)+" ist ein Geist!\n"); 00121 return 0; 00122 } 00123 00124 damage=(damage*(int)caster->QuerySkillAttribute(SA_DAMAGE))/100; 00125 00126 // ggf. Loggen von PK-Versuchen 00127 if (query_once_interactive(caster) && query_once_interactive(victim)) 00128 CheckPlayerAttack(caster, victim, sprintf("Spellbook: %O, Spell: %O\n", 00129 object_name(this_object()), 00130 ((mappingp(sinfo) && is_spell) ? sinfo[SP_NAME] : "") ) ); 00131 00132 nomag=(int)victim->QueryProp(P_NOMAGIC); 00133 if ((sinfo[SI_NOMAGIC] < nomag) && 00134 nomag*100 > random(100)*(int)caster->QuerySkillAttribute(SA_ENEMY_SAVE)) { 00135 printf("%s wehrt Deinen Zauber ab.\n", capitalize((string)victim->name(WER, 1))); 00136 return 0; 00137 } 00138 else { 00139 return (int)victim->Defend(damage, dtypes, is_spell, caster); 00140 } 00141 }


| varargs int TryDefaultAttackSpell | ( | object | victim, | |
| object | caster, | |||
| mapping | sinfo, | |||
| mixed | si_spell | |||
| ) |
Definiert in Zeile 144 der Datei spellbook.c.
Benutzt GetData(), GetRandFValueO(), OFFSET, P_TEAM, SI_SKILLDAMAGE, SI_SKILLDAMAGE_BY_ROW, SI_SKILLDAMAGE_TYPE, SI_SPELL, team und TryAttackSpell().
Wird benutzt von feuerball(), pfeil() und saeurestrahl().
00145 { 00146 object team; 00147 int row; 00148 00149 if (!si_spell) si_spell=sinfo[SI_SPELL]; 00150 // Wenn der Spieler in einem Team ist, die Teamreihen-Boni 00151 // beruecksichtigen. Wenn nicht, eben nicht. 00152 if (!team=((object)caster->QueryProp(P_TEAM))) 00153 return TryAttackSpell(victim, 00154 GetRandFValueO(SI_SKILLDAMAGE,sinfo,caster), 00155 GetData(SI_SKILLDAMAGE_TYPE,sinfo,caster), 00156 si_spell, 00157 caster, 00158 sinfo); 00159 else 00160 { 00161 row=(int)caster->PresentPosition(); 00162 return TryAttackSpell(victim, 00163 GetRandFValueO(SI_SKILLDAMAGE,sinfo,caster)+ 00164 // Nur wenn SI_SKILLDAMAGE_BY_ROW ein mapping ist, 00165 // randomisiert addieren 00166 (mappingp(sinfo[SI_SKILLDAMAGE_BY_ROW])? 00167 random(sinfo[SI_SKILLDAMAGE_BY_ROW][row]):0)+ 00168 // Nur wenn das OFFSET davon ein mapping ist, 00169 // nicht randomisiert addieren. 00170 (mappingp(sinfo[OFFSET(SI_SKILLDAMAGE_BY_ROW)])? 00171 sinfo[OFFSET(SI_SKILLDAMAGE_BY_ROW)][row] : 0), 00172 GetData(SI_SKILLDAMAGE_TYPE,sinfo,caster), 00173 si_spell,caster,sinfo); 00174 } 00175 }


| varargs int TryGlobalAttackSpell | ( | object | caster, | |
| mapping | sinfo, | |||
| int | suc, | |||
| int | damage, | |||
| mixed | dt, | |||
| mixed | is_spell, | |||
| int | dist, | |||
| int | depth, | |||
| int | width | |||
| ) |
Definiert in Zeile 689 der Datei spellbook.c.
Benutzt FindDistantGroups(), GetData(), GetRandFValueO(), obs, SI_COLLATERAL_DAMAGE, SI_DEPTH, SI_DISTANCE, SI_NUMBER_ENEMIES, SI_NUMBER_FRIENDS, SI_SKILLABILITY, SI_SKILLDAMAGE, SI_SKILLDAMAGE_TYPE, SI_SPELL, SI_WIDTH, SP_GLOBAL_ATTACK und TryAttackSpell().
00691 { 00692 int i; 00693 mixed x,coldam; 00694 object *obs,ob; 00695 00696 if (!suc) suc=random(sinfo[SI_SKILLABILITY]); 00697 if (!dt) dt=GetData(SI_SKILLDAMAGE_TYPE,sinfo,caster); 00698 if (!is_spell) is_spell=GetData(SI_SPELL,sinfo,caster); 00699 if (!dist) dist=GetRandFValueO(SI_DISTANCE,sinfo,caster); 00700 if (!depth) depth=GetRandFValueO(SI_DEPTH,sinfo,caster); 00701 if (!width) width=GetRandFValueO(SI_WIDTH,sinfo,caster); 00702 00703 if (!depth && width) depth=width; 00704 if (!width && depth) width=depth; 00705 if (!mappingp(is_spell)) is_spell=([]); 00706 is_spell[SP_GLOBAL_ATTACK]=1; 00707 00708 x=FindDistantGroups(caster,dist,depth,width); 00709 sinfo[SI_NUMBER_ENEMIES]=sizeof(x[0]); 00710 sinfo[SI_NUMBER_FRIENDS]=sizeof(x[1]); 00711 00712 obs=x[0]; 00713 for (i=sizeof(obs)-1;i>=0;i--) 00714 if (objectp(ob=obs[i]) && suc>=ob->SpellDefend(caster,sinfo)) 00715 TryAttackSpell(ob,(damage?random(damage): 00716 GetRandFValueO(SI_SKILLDAMAGE,sinfo,caster)), 00717 dt,is_spell,caster,sinfo); 00718 00719 if (!intp(coldam=sinfo[SI_COLLATERAL_DAMAGE]) || !coldam) 00720 return 1; 00721 obs=x[1]; 00722 for (i=sizeof(obs)-1;i>=0;i--) 00723 if (objectp(ob=obs[i]) && suc>=ob->SpellDefend(caster,sinfo)) 00724 ob->reduce_hit_points(((damage?random(damage): 00725 GetRandFValueO(SI_SKILLDAMAGE,sinfo,caster)) 00726 *coldam)/10); 00727 // 10 statt 100 ist Absicht, weil reduce_hit_points schon um Faktor 00728 // 10 staerker wirkt als Defend. 00729 00730 return 1; 00731 }

| varargs int UseSpell | ( | object | caster, | |
| string | spell, | |||
| mapping | sinfo | |||
| ) |
Definiert in Zeile 271 der Datei spellbook.c.
Benutzt ABGEWEHRT, AddSkillMappings(), CanTrySpell(), Erfolg(), ERFOLG, GetFValueO(), GetValue(), Misserfolg(), MISSERFOLG, NO_ATTACK_BUSY_QUERY, P_ATTACK_BUSY, P_NEXT_SPELL_TIME, P_NOMAGIC, P_PREPARED_SPELL, P_SP, prepare_spell(), QueryProp(), QuerySpell(), race_modifier(), SelectSpell(), SI_ATTACK_BUSY_AMOUNT, SI_ATTACK_BUSY_MSG, SI_NO_ATTACK_BUSY, SI_NOMAGIC, SI_NOMAGIC_MSG, SI_PREPARE_ABORT_MSG, SI_PREPARE_BUSY_MSG, SI_PREPARE_TIME, SI_SKILLARG, SI_SKILLFUNC, SI_SP_LOW_MSG, SI_SPELLCOST, SI_SPELLFATIGUE, SI_TIME_MSG und spellbook.
00271 { 00272 mapping ski,tmp; 00273 string spellbook,sname,fname,txt; 00274 int res,fat,cost; 00275 mixed ps; 00276 00277 if (!caster || !spell) 00278 return 0; 00279 sname=SelectSpell(spell,sinfo); 00280 // Spell kann in der Gilde anderen Namen haben 00281 if (!(ski=QuerySpell(sname))) // Existiert dieser Spell? 00282 return 0; 00283 ski=AddSkillMappings(ski,sinfo); 00284 // Gildeneigenschaften sollen Spelleigenschaften ueberschreiben koennen 00285 ski=race_modifier(caster,ski); 00286 // Fuer verschiedene Rassen unterschiedliche Eigenschaften 00287 00288 // printf("Spellinfo: %O\n",ski); 00289 00290 if (!CanTrySpell(caster, ski)) 00291 return 1; 00292 if (caster->QueryProp(P_SP) < (cost=GetFValueO(SI_SPELLCOST,ski,caster))) { 00293 if(txt=ski[SI_SP_LOW_MSG])write(txt); 00294 else write("Du hast zu wenig Zauberpunkte fuer diesen Spruch.\n"); 00295 return 1; 00296 } 00297 // printf("cost: %d\n",cost); 00298 #if __BOOT_TIME__ < 1268687556 00299 if (time()<caster->QueryProp(P_NEXT_SPELL_TIME)) { 00300 #else 00301 if (caster->CheckSpellFatigue()) { 00302 #endif 00303 if(txt=ski[SI_TIME_MSG]) write(txt); 00304 else write("Du bist noch zu erschoepft von Deinem letzten Spruch.\n"); 00305 return 1; 00306 } 00307 if (!(ski[SI_NO_ATTACK_BUSY]&NO_ATTACK_BUSY_QUERY) && 00308 caster->QueryProp(P_ATTACK_BUSY)) { 00309 if (txt=ski[SI_ATTACK_BUSY_MSG]) write(txt); 00310 else write("Du bist schon zu sehr beschaeftigt.\n"); 00311 return 1; 00312 } 00313 00314 // Spruchvorbereitung 00315 if (pointerp(ps=(mixed)caster->QueryProp(P_PREPARED_SPELL)) // Ausstehender Spruch 00316 && sizeof(ps)>=3 && intp(ps[0] && stringp(ps[1]))) { 00317 if (ps[1]==spell) { // Dieser Spruch wird noch vorbereitet 00318 if (time()<ps[0]) { 00319 if (!stringp(txt=ski[SI_PREPARE_BUSY_MSG])) 00320 txt="Du bist noch mit der Spruchvorbereitung beschaeftigt.\n"; 00321 write(txt); 00322 return 1; 00323 } 00324 } else { // Andere Sprueche brechen die Vorbereitung ab 00325 if (!mappingp(tmp=QuerySpell(ps[1])) || // richtige Meldung holen... 00326 !stringp(txt=tmp[SI_PREPARE_ABORT_MSG])) 00327 txt="Du brichst die Spruchvorbereitung fuer `%s' ab.\n"; 00328 printf(txt,ps[1]); 00329 if (fat=GetValue(SI_PREPARE_TIME,ski,caster)) { 00330 // Spruch braucht vorbereitungszeit 00331 caster->SetProp(P_PREPARED_SPELL,({time()+fat,spell,ski[SI_SKILLARG]})); 00332 prepare_spell(caster,spell,ski); 00333 return 1; 00334 } 00335 } 00336 } else { 00337 if (fat=GetValue(SI_PREPARE_TIME,ski,caster)) { 00338 // Spruch braucht vorbereitungszeit 00339 caster->SetProp(P_PREPARED_SPELL,({time()+fat,spell,ski[SI_SKILLARG]})); 00340 prepare_spell(caster,spell,ski); 00341 return 1; 00342 } 00343 } 00344 if (ps) 00345 caster->SetProp(P_PREPARED_SPELL,0); 00346 00347 if (!(fname=sinfo[SI_SKILLFUNC])) 00348 fname=sname; 00349 // Funktion kann anderen Namen haben als Spell 00350 res=0; 00351 if((ski[SI_NOMAGIC] < environment(caster)->QueryProp(P_NOMAGIC)) && 00352 random(100) < environment(caster)->QueryProp(P_NOMAGIC)) { 00353 if (txt=ski[SI_NOMAGIC_MSG]) write(txt); 00354 else write("Dein Zauberspruch verpufft im Nichts.\n"); 00355 res=ABGEWEHRT; 00356 } else { 00357 res=(int)call_other(this_object(),fname,caster,ski); 00358 } 00359 if (!res || !caster) 00360 return 1; 00361 00362 if (!(ski[SI_NO_ATTACK_BUSY]&NO_ATTACK_BUSY_QUERY)) 00363 { 00364 if (!ski[SI_ATTACK_BUSY_AMOUNT]) 00365 caster->SetProp(P_ATTACK_BUSY,1); 00366 else 00367 caster->SetProp(P_ATTACK_BUSY,ski[SI_ATTACK_BUSY_AMOUNT]); 00368 } 00369 if ((fat=GetFValueO(SI_SPELLFATIGUE,ski,caster))<0) 00370 fat=1; 00371 caster->restore_spell_points(-1*cost); 00372 #if __BOOT_TIME < 1268687556 00373 caster->SetProp(P_NEXT_SPELL_TIME,time()+fat); 00374 #else 00375 caster->SetSpellFatigue(fat); 00376 #endif 00377 00378 if (res==ERFOLG) 00379 Erfolg(caster,spell,ski); 00380 else 00381 if (res==MISSERFOLG) 00382 Misserfolg(caster,spell,ski); 00383 return 1; 00384 }

Definiert in Zeile 16 der Datei spellbook.c.
| inherit std restriction_checker |
Definiert in Zeile 15 der Datei spellbook.c.
| inherit std thing |
Definiert in Zeile 14 der Datei spellbook.c.
1.6.3