blob: 03755da371014034980bd93841609674afc30a51 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2//
3// player/skills.c -- Spielerskills
4//
5// $Id: skills.c 8809 2014-05-08 19:52:48Z Zesstra $
6
7//
8// 2003-01-20: Nun Zooks Baustelle
9//
10#pragma strong_types
11#pragma save_types
12#pragma range_check
13#pragma no_clone
14#pragma pedantic
15
16inherit "/std/living/skills";
17
18#include <combat.h>
19#include <new_skills.h>
20#include <properties.h>
21#include <break_string.h>
22#include <wizlevels.h>
23
24#define NEED_PROTOTYPES
25#include <player/base.h>
26#include <player/gmcp.h>
27#undef NEED_PROTOTYPES
28
29// Dieses Mapping speichert die deaktivierten Skills der einzelnen Gilden
30// Diese werden in den Gilden ueber P_GUILD_DEACTIVATED_SKILL gesetzt.
31nosave mapping deactivated_skills = ([]);
32
33// Flag fuer den Kompatibilitaetsmodus des Kampfs (Emulation von
34// 2s-Alarmzeit). Wenn != 0 speichert das Flag gleichzeitig die Zeit des
35// letzten Heartbeats. Auf diese Zeit wird der Startpunkt eines Spellfatigues
36// ggf. zurueckdatiert. (max. eine Sekunde)
37int spell_fatigue_compat_mode;
38
39// Ein create() fuer das Mapping
40
41protected void create()
42{
43 mapping act;
44
45 ::create();
46
47 // Wir holen die Gilden aus dem Gildenmaster
48 foreach(string guild:
49 (string *)call_other(GUILDMASTER,"QueryProp",P_VALID_GUILDS))
50 {
51 if(catch(act=call_other("/gilden/"+guild,"QueryProp",
52 P_GUILD_DEACTIVATE_SKILLS); publish ))
53 log_file("WEAPON_SKILLS", sprintf ("%s: Gilde nicht ladbar: "
54 +"TP: %O, TI: %O, PO: %O, Gilde: %s\n", dtime(time()),
55 this_player(), this_interactive(), previous_object(), guild));
56 else if (act) // wenn act, ins Mapping aufnehmen.
57 deactivated_skills+=([guild:act]);
58 }
59 // keine echte Prop mehr, Save-Modus unnoetig.
60 Set(P_NEXT_SPELL_TIME,SAVE,F_MODE_AD);
61
62 Set(P_SKILLSVERSION, SAVE|SECURED, F_MODE_AS);
63}
64
65// Das Mapping kann man auch abfragen
66
67public mapping GetDeactivatedSkills()
68{
69 return copy(deactivated_skills);
70}
71
72// Funktion, die sagt ob ein ANY-Skill deaktiviert ist.
73public int is_deactivated_skill(string sname,string guild)
74{
75 if (deactivated_skills[guild])
76 return deactivated_skills[guild][sname];
77 return 0;
78}
79
80
81// Funktion fuer die Waffenskills
82// traegt die allg. Waffenskills ein. Wird ggf. von FixSkills() gerufen.
83// (Das Eintragen bedeutet nicht, dass die aktiv sind! Aber bei Gildenwechsel
84// werden sie nicht eingetragen).
85private void set_weapon_skills() {
86
87 if (QuerySkillAbility(FIGHT(WT_SWORD))<=0)
88 ModifySkill(FIGHT(WT_SWORD),([SI_SKILLABILITY:0]),150,"ANY");
89 if (QuerySkillAbility(FIGHT(WT_AXE))<=0)
90 ModifySkill(FIGHT(WT_AXE),([SI_SKILLABILITY:0]),150,"ANY");
91 if (QuerySkillAbility(FIGHT(WT_SPEAR))<=0)
92 ModifySkill(FIGHT(WT_SPEAR),([SI_SKILLABILITY:0]),150,"ANY");
93 if (QuerySkillAbility(FIGHT(WT_WHIP))<=0)
94 ModifySkill(FIGHT(WT_WHIP),([SI_SKILLABILITY:0]),150,"ANY");
95 if (QuerySkillAbility(FIGHT(WT_KNIFE))<=0)
96 ModifySkill(FIGHT(WT_KNIFE),([SI_SKILLABILITY:0]),150,"ANY");
97 if (QuerySkillAbility(FIGHT(WT_CLUB))<=0)
98 ModifySkill(FIGHT(WT_CLUB),([SI_SKILLABILITY:0]),150,"ANY");
99 if (QuerySkillAbility(FIGHT(WT_STAFF))<=0)
100 ModifySkill(FIGHT(WT_STAFF),([SI_SKILLABILITY:0]),150,"ANY");
101}
102
103// initialisiert die Skills fuer Spieler (momentan: allg. Waffenskills setzen
104// und P_SKILLS_VERSION)
105protected void InitSkills() {
106 mapping ski;
107 // schonmal initialisiert?
108 if (mappingp(ski=Query(P_NEWSKILLS, F_VALUE)) && sizeof(ski))
109 return;
110
111 // allg. Waffenskills aktivieren
112 set_weapon_skills();
113
114 // Version setzen
115 SetProp(P_SKILLSVERSION, CURRENT_SKILL_VERSION);
116 Set(P_SKILLSVERSION, SAVE|SECURED, F_MODE_AS);
117}
118
119// Updated Skills aus Version 0 und 1 heraus.
120private void FixSkillV1(string skillname, mixed sinfo) {
121 // alte Skills auf mappings normieren
122 if (intp(sinfo)) {
123 sinfo = ([SI_SKILLABILITY: sinfo ]);
124 }
125 // Eine Reihe von Daten werden geloescht, da die Daten aus der
126 // Gilde/Spellbook frisch kommen sollten und sie nicht spieler-individuell
127 // sind: SI_CLOSURE (wird onthefly korrekt neu erzeugt), SI_SKILLARG,
128 // SI_NUMBER_ENEMIES, SI_NUMBER_FRIENDS, SI_DISTANCE, SI_WIDTH, SI_DEPTH,
129 // SI_TESTFLAG, SI_ENEMY, SI_FRIEND.
130 // Ausserdem sind alle SP_* im toplevel falsch, die muessen a) in SI_SPELL
131 // und sollten b) nicht im Spieler gespeichert werden, sondern von
132 // Gilden/Spellbook jeweils frisch kommen.
133 // all dieses Zeug landete in alten Spielern im Savefile.
134 if (mappingp(sinfo))
135 sinfo -= ([SI_CLOSURE, SI_SKILLARG, SI_NUMBER_ENEMIES, SI_NUMBER_FRIENDS,
136 SI_DISTANCE, SI_WIDTH, SI_DEPTH, SI_TESTFLAG, SI_ENEMY,
137 SI_FRIEND, SP_NAME, SP_SHOW_DAMAGE, SP_REDUCE_ARMOUR,
138 SP_PHYSICAL_ATTACK, SP_RECURSIVE, SP_NO_ENEMY,
139 SP_NO_ACTIVE_DEFENSE, SP_GLOBAL_ATTACK ]);
140 else
141 {
142 tell_object(this_object(),sprintf(
143 "\n**** ACHTUNG - FEHLER ***\n"
144 "Deine Skills enthalten einen defekten Skill %O:\n"
145 "Bitte lass dies von einem Erzmagier ueberpruefen.\n",
146 skillname));
147 }
148}
149
150// Updatet und repariert ggf. Skillmappings in Spielern
151protected void FixSkills() {
152
153 // nur bei genug rechenzeit loslegen
154 if (get_eval_cost() < 750000) {
155 call_out(#'FixSkills, 1);
156 return;
157 }
158 // wenn gar keine Skills da (?): InitSkills() rufen.
159 mapping allskills = Query(P_NEWSKILLS, F_VALUE);
160 if (!mappingp(allskills) || !sizeof(allskills)) {
161 InitSkills();
162 return;
163 }
164
165 // Die Fallthroughs in diesem switch sind voll Absicht!
166 switch(QueryProp(P_SKILLSVERSION)) {
167 // bei Version 0 und 1 das gleiche tun
168 case 0: // von 0 auf 1
169 case 1: // von 1 auf 2
170 foreach(string gilde, mapping skills: allskills) {
171 if (!stringp(gilde)) {
172 // sollte nicht vorkommen - tat aber... *seufz*
173 m_delete(skills, gilde);
174 continue;
175 }
176 walk_mapping(skills, #'FixSkillV1);
177 }
178 // allg. Waffenskills aktivieren, einige alte Spieler haben die noch
179 // nicht.
180 set_weapon_skills();
181 // Speicherflag fuer die Versionsprop muss noch gesetzt werden.
182 Set(P_SKILLSVERSION, SAVE|SECURED, F_MODE_AS);
183 // Version ist jetzt 2.
184 SetProp(P_SKILLSVERSION, 2);
185 // Fall-through
186 case 2:
187 // gibt es noch nicht, nichts machen.
188 //SetProp(P_SKILLSVERSION, 3);
189 // Fall-through, ausser es sind zuwenig Ticks da!
190 if (get_eval_cost() < 750000)
191 break;
192 }
193 // Falls noch nicht auf der aktuellen Version angekommen, neuer callout
194 if (QueryProp(P_SKILLSVERSION) < CURRENT_SKILL_VERSION)
195 call_out(#'FixSkills, 2);
196}
197
198protected void updates_after_restore(int newflag) {
199 //Allgemeine Waffenskills aktivieren, wenn noetig
200 // Wird nun von InitSkills bzw. FixSkills uebernommen, falls noetig.
201 if (newflag) {
202 InitSkills();
203 }
204 else if (QueryProp(P_SKILLSVERSION) < CURRENT_SKILL_VERSION) {
205 // Falls noetig, Skills fixen/updaten. *grummel*
206 FixSkills();
207 }
208 // Prop gibt es nicht mehr. SAVE-Status loeschen.
209 Set(P_GUILD_PREVENTS_RACESKILL,SAVE,F_MODE_AD);
210}
211
212// Standardisierte Nahkampf-Funktion fuer alle Nahkampf-Waffenarten
213protected mapping ShortRangeSkill(object me, string sname, mapping sinfo)
214{
215 int val, w;
216 object enemy;
217
218 if (!mappingp(sinfo) || !objectp(sinfo[P_WEAPON]))
219 return 0;
220
221 w = ([WT_KNIFE : 8,
222 WT_SWORD : 5,
223 WT_AXE : 4,
224 WT_SPEAR : 6,
225 WT_CLUB : 1,
226 WT_WHIP : 9,
227 WT_STAFF : 7])[sinfo[P_WEAPON]->QueryProp(P_WEAPON_TYPE)];
228
229
230 val = sinfo[SI_SKILLABILITY]*(sinfo[P_WEAPON]->QueryProp(P_WC)*
231 (w*QueryAttribute(A_DEX)+
232 (10-w)*QueryAttribute(A_STR))/700)
233 /MAX_ABILITY;
234
235 if (val > 85) {
236 log_file("WEAPON_SKILLS", sprintf("%s: Zu hoher Schaden von: "
237 +"TO: %O, TI: %O, PO: %O, val: %d, A_DEX: %d, A_STR: %d, "
238 +"P_WEAPON: %O, P_WC: %d\n", dtime(time()),
Zesstra9ad254c2019-09-27 00:30:41 +0200239 this_object(), this_interactive(),
240 previous_object(), val,
MG Mud User88f12472016-06-24 23:31:02 +0200241 QueryAttribute(A_DEX),
242 QueryAttribute(A_STR), sinfo[P_WEAPON],
243 sinfo[P_WEAPON]->QueryProp(P_WC)));
244 val = 85;
245 }
246
247 /*
Zesstra9ad254c2019-09-27 00:30:41 +0200248 Der zusaetzliche Schaden der allgemeinen Waffenskills berechnet
MG Mud User88f12472016-06-24 23:31:02 +0200249 sich wie folgt:
250
251 sinfo[SI_SKILLABILITY)* (P_WC * ( X ) / 800) / MAX_ABILITY
252
253 Dabei beruecksichtigt X je nach Waffentyp in unterschiedlicher
254 Gewichtung die Werte fuer Geschicklichkeit und Staerke.
255
256 X ==
257
258 Messer : 8*A_DEX + 2*A_STR
259 Schwert : 5*A_DEX + 5*A_STR
260 Axt : 4*A_DEX + 6*A_STR
261 Speer : 6*A_DEX + 4*A_STR
262 Keule : 1*A_DEX + 9*A_STR
263 Peitsche : 9*A_DEX + 1*A_STR
264 */
265
266 sinfo[SI_SKILLDAMAGE]+=val;
267
268
269 /* Lernen: Wird immer schwieriger, nur bei jedem 20. Schlag im Schnitt,
Drache Humnidb9f15f2018-03-15 22:00:18 +0100270 * und nur dann, wenn der Gegner auch XP gibt.
271 * EM-Beschluss: Lernen wird leichter (jeder 5. Schlag, skillabhaengig)
272 * und bei jedem 300. Schlag lernt man auch so. Ferner wird noch
273 * ueberprueft, ob der Skill schon maximal ist, wenn man sonst in
274 * jedem Falle lernen wurde.
275 */
276 if ((random(MAX_ABILITY+1)>sinfo[SI_SKILLABILITY] && !random(5))
277 || (!random(300) && sinfo[SI_SKILLABILITY]<MAX_ABILITY))
MG Mud User88f12472016-06-24 23:31:02 +0200278 {
279 enemy=sinfo[SI_ENEMY];
280 if (objectp(enemy) && (enemy->QueryProp(P_XP)>0))
281 {
282 object ausbilder;
283 // log_file("humni/log_wurm","Haut: %s und zwar %s, mit xp %d\n",geteuid(this_object()),to_string(enemy),enemy->QueryProp(P_XP));
284 LearnSkill(sname, random(5), 150);
285 // Gibt es einen Ausbilder?
286 if (QueryProp(P_WEAPON_TEACHER) &&
287 ausbilder=find_player(QueryProp(P_WEAPON_TEACHER)))
288 {
289 // Ist der Ausbilder anwesend?
290 if (present(ausbilder,environment()))
291 {
292 // Ausbilder und Azubi muessen dieselbe Waffe haben.
293 //string wt_aus,wt_azu;
294 object waf_aus,waf_azu;
295
296 waf_azu=QueryProp(P_WEAPON);
297 waf_aus=call_other(ausbilder,"QueryProp",P_WEAPON);
298
299 //wt_azu=call_other(waf_azu,"QueryProp",P_WEAPON_TYPE);
300 //wt_aus=call_other(waf_aus,"QueryProp",P_WEAPON_TYPE);
301 //if (wt_azu==wt_aus)
302 if (objectp(waf_aus) && objectp(waf_azu) &&
303 (string)waf_aus->QueryProp(P_WEAPON_TYPE)
304 == (string)waf_azu->QueryProp(P_WEAPON_TYPE))
305 {
306 // Bonus von bis zu 5 Punkten
307 //log_file("humni/log_azubi",
308 // sprintf("Azubi %O und Ausbilder %O : Waffentypen %s und %s, gelernt\n",this_object(),
309 // ausbilder, wt_azu, wt_aus));
310 LearnSkill(sname,random(6),150);
311 }
312 }
313 }
314 }
315 }
316
317 /*
318 Die Schwierigkeit liegt bei 150, so dass
319 ein Lvl. 1 Spieler maximal 15% Skill
320 usw...
321 lernen kann. (Genaue Tabelle in /std/living/skills bei LimitAbility)
322 */
323
324 return sinfo;
325}
326
327
328// Standardisierte Fernkampf-Funktion fuer alle Fernkampf-Waffenarten
329
330// *** noch deaktiviert ***
331
332protected mapping LongRangeSkill(object me, string sname, mapping sinfo, int dam)
333{ int abil,val;
334
335 if (!mappingp(sinfo) || !dam || !objectp(sinfo[P_WEAPON]) ||
336 (sinfo[P_WEAPON]->QueryProp(P_SHOOTING_WC))<5)
337 return 0;
338
339 abil=sinfo[SI_SKILLABILITY]+sinfo[OFFSET(SI_SKILLABILITY)];
340 val=dam*abil/MAX_ABILITY;
341 val=val/2+random(val/2+1);
342 val=(val*QuerySkillAttribute(SA_DAMAGE))/100;
343 sinfo[SI_SKILLDAMAGE]+=val;
344
345 if (random(MAX_ABILITY+1)>sinfo[SI_SKILLABILITY] && random(50)==42)
346 LearnSkill(sname, 1, 150);
347
348 return sinfo;
349}
350
351
352
353// Die einzelnen Waffenskills rufen dann nur die Standard-Funktion auf.
354
355protected mapping StdSkill_Fight_axe(object me, string sname, mapping sinfo)
356{
357 return ShortRangeSkill(me, sname, sinfo);
358}
359
360protected mapping StdSkill_Fight_club(object me, string sname, mapping sinfo)
361{
362 return ShortRangeSkill(me, sname, sinfo);
363}
364
365protected mapping StdSkill_Fight_knife(object me, string sname, mapping sinfo)
366{
367 return ShortRangeSkill(me, sname, sinfo);
368}
369
370protected mapping StdSkill_Fight_spear(object me, string sname, mapping sinfo)
371{
372 return ShortRangeSkill(me, sname, sinfo);
373}
374
375protected mapping StdSkill_Fight_sword(object me, string sname, mapping sinfo)
376{
377 return ShortRangeSkill(me, sname, sinfo);
378}
379
380protected mapping StdSkill_Fight_whip(object me, string sname, mapping sinfo)
381{
382 return ShortRangeSkill(me, sname, sinfo);
383}
384
385protected mapping StdSkill_Fight_staff(object me, string sname, mapping sinfo)
386{
387 return ShortRangeSkill(me, sname, sinfo);
388}
389
390
391
392
393// Die Fernwaffenskills sind Munitionsabhaengig
394
395// *** noch deaktiviert ***
396
397protected mapping StdSkill_Shoot_arrow(object me, string sname, mapping sinfo)
398{
399 return LongRangeSkill(me, sname, sinfo, 40);
400}
401
402protected mapping StdSkill_Shoot_bolt(object me, string sname, mapping sinfo)
403{
404 return LongRangeSkill(me, sname, sinfo, 40);
405}
406
407protected mapping StdSkill_Shoot_dart(object me, string sname, mapping sinfo)
408{
409 return LongRangeSkill(me, sname, sinfo, 20);
410}
411
412protected mapping StdSkill_Shoot_stone(object me, string sname, mapping sinfo)
413{
414 return LongRangeSkill(me, sname, sinfo, 40);
415}
416
417protected mixed _query_localcmds() {
418 return ({ ({"spruchermuedung","enable_spell_fatigue_compat",0,0}) });
419}
420
421
422
423// *** Kompatibilitaetsmodus fuer Spellfatigues (Emulation 2s-Alarmzeit) ***
424
425/** Speichert eine Spellfatigue von <duration> Sekunden fuer <key>.
426 * Ist hier nur fuer den Spellfatigue-Compat-mode.
427 * <key> darf 0 sein und bezeichnet das globale Spellfatigue.
428 * Rueckgabewert: Ablaufzeit der gesetzten Sperre
429 -1, wenn noch eine nicht-abgelaufene Sperre auf dem <key> lag.
430 0, wenn duration 0 ist.
431 */
432public varargs int SetSpellFatigue(int duration, string key) {
433
434 // 0 sollte nie eine Sperre bewirken, auch nicht im compat mode.
435 if (!duration) return 0;
436
437 if (spell_fatigue_compat_mode) {
438 // Spell-Fatigues auf HBs synchronisieren (2s-Alarmzeit-Emulation).
439 // Aufrunden auf ganzzahlige Vielfache von __HEART_BEAT_INTERVAL__
440 if (duration % __HEART_BEAT_INTERVAL__)
441 ++duration;
442
443 // Startpunkt des Delay soll Beginn der aktuellen Kampfrunde (HB-Zyklus)
444 // sein, ggf. um max. eine Sekunde zurueckdatieren.
445 // (spell_fatigue_compat_mode hat die Zeit des letzten HB-Aufrufs)
446 // Falls durch irgendein Problem (z.B. sehr hohe Last), der letzte HB
447 // laenger als 1s zurueckliegt, funktioniert das natuerlich nicht, aber
448 // bei fatigue+=spell_fatigue_compat_mode kann der Spieler zuviel Zeit
449 // einsparen.
450 if (time() > spell_fatigue_compat_mode)
451 --duration; //1s zurueckdatieren
452 }
453
454 return ::SetSpellFatigue(duration, key);
455}
456
457/** Befehlsfunktion fuer Spieler um den Spellfatigue-Kompatibilitaetsmodus
458 * umzuschalten.
459 */
460public int enable_spell_fatigue_compat(string cmd) {
461 if (QueryProp(P_LAST_COMBAT_TIME) + 600 > time()) {
462 write(break_string(
463 "Im Kampf oder kurz nach einem Kampf kannst Du nicht zwischen "
464 "alter und neuer Spruchermuedung umschalten.\n"
465 "Momentan benutzt Du die "
466 + (spell_fatigue_compat_mode ? "alte (ungenauere)" : "neue (normale)")
467 + " Spruchermuedung.",78,0,BS_LEAVE_MY_LFS));
468 return 1;
469 }
470
471 if (cmd=="alt") {
472 spell_fatigue_compat_mode=time();
473 write(break_string(
474 "Alte Spruchermuedung wurde eingeschaltet. Alle Ermuedungspausen "
475 "zwischen Spruechen werden auf Vielfache von 2s aufgerundet und "
476 "beginnen in der Regel am Anfang Deiner Kampfrunde."));
477 return 1;
478 }
479 else if (cmd=="neu" || cmd=="normal") {
480 spell_fatigue_compat_mode=0;
481 write(break_string(
482 "Normale Spruchermuedung wurde eingeschaltet. Alle Ermuedungspausen "
483 "zwischen Spruechen werden sekundengenau berechnet."));
484 return 1;
485 }
486
487 notify_fail(break_string(
488 "Moechtest Du die alte oder die neue Spruchermuedung?\n"
489 "Momentan benutzt Du die "
490 + (spell_fatigue_compat_mode ? "alte (ungenauere)" : "neue (normale)")
491 + " Spruchermuedung.",78,0,BS_LEAVE_MY_LFS));
492 return 0;
493}
494
495/** Speichert die Zeit des letztes Heartbeats.
496 */
497protected void heart_beat() {
498 if (spell_fatigue_compat_mode)
499 spell_fatigue_compat_mode = time();
500}
501
502static int _set_guild_level(int num)
503{ string gilde;
504 mapping levels;
505
506 if ( !(gilde=QueryProp(P_GUILD)) )
507 return 0;
508
509 if ( !mappingp(levels=Query(P_GUILD_LEVEL)) )
510 levels=([]);
511
512 levels[gilde]=num;
513 Set(P_GUILD_LEVEL,levels);
514 GMCP_Char( ([P_GUILD_LEVEL: num]) );
515
516 return num;
517}
518
519static int _query_guild_level()
520{ string gilde;
521 mapping levels;
522
523 if ( !(gilde=QueryProp(P_GUILD)) )
524 return 0;
525
526 if ( !mappingp(levels=Query(P_GUILD_LEVEL)) )
527 return 0;
528
529 return levels[gilde];
530}
531
532static string _set_guild_title(string t)
533{ string gilde;
534 mapping titles;
535
536 if ( !(gilde=QueryProp(P_GUILD)) )
537 return 0;
538
539 if ( !mappingp(titles=Query(P_GUILD_TITLE)) )
540 titles=([]);
541
542 titles[gilde]=t;
543 Set(P_GUILD_TITLE,titles);
544 GMCP_Char( ([P_GUILD_TITLE: t]) );
545 return t;
546}
547
548static string _query_guild_title()
549{ string gilde,t;
550 object g;
551 mapping titles;
552
553 if ( !(gilde=QueryProp(P_GUILD)) )
554 return 0;
555
556 if ( !mappingp(titles=Query(P_GUILD_TITLE)) )
557 titles=([]);
558
559 t=titles[gilde];
560 if ( !t && query_once_interactive(this_object())
561 && objectp(g=find_object("/gilden/"+gilde)) )
562 {
563 g->adjust_title(this_object());
564 SetProp(P_TITLE,0);
565
566 if ( !mappingp(titles=Query(P_GUILD_TITLE)) )
567 return 0;
568
569 t=titles[gilde];
570 }
571
572 return t;
573}
574
575
576static string _set_guild(string gildenname)
577{ object pre;
578
579 if (!objectp(pre=previous_object()))
580 return 0;
581
582 if ( pre!=this_object() // Das Lebewesen selber darf die Gilde setzen,
583 && object_name(pre)!=GUILDMASTER // der Gildenmaster auch
584 && (!this_player()
585 || this_player() != this_interactive()
586 || !IS_ARCH(this_player())
587 )
588 )
589 return 0;
590
591 Set(P_GUILD,gildenname);
592 GMCP_Char( ([P_GUILD: gildenname]) );
593 return gildenname;
594}
595
596static string _query_guild()
597{ string res;
598
599 if ( !(res=Query(P_GUILD)) && query_once_interactive(this_object()) )
600 {
601 // Spieler, die keiner Gilde angehoeren, gehoeren zur Abenteurergilde
602 if ( !(res=QueryProp(P_DEFAULT_GUILD)) )
603 return DEFAULT_GUILD;
604 else
605 Set(P_GUILD,res);
606 return res;
607 }
608
609 return res;
610}
611
612static string _query_title()
613{ string ti;
614
615 if ( stringp(ti=Query(P_TITLE)) )
616 return ti;
617
618 return QueryProp(P_GUILD_TITLE);
619}
620
621static string _set_title(string t)
622{
623 Set(P_TITLE, t, F_VALUE);
624 GMCP_Char( ([P_TITLE: t]) );
625 return t;
626}
627