blob: 3997584acb1bce831952985d45fec7244c5b9d8a [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001/*Fisch-Master, (c) Vanion@MG, 26.05.02
2
3 Fische die im MG geangelt werden koennen, sollen nicht als endlose
4 Geldquelle dienen. Daher habe ich einen Master gebaut, der sich merkt
5 Welcher Spieler wieviel Fisch geangelt hat. Je mehr Fisch der Spieler
6 faengt, desto billiger wird der Fisch.
7
8 Schnittstelle:
9
10 Der Master hat abgesehen von Standard-Funktionen nur eine Schnittstelle
11
12 public int PriceOfFish(object player, object fish)
13
14 Der erste Parameter ist der Spieler, der den Fisch gecloned hat, der
15 zweite ist der Fisch, den der Spieler gefangen hat. Der Fisch muss
16 hierbei von Fraggles Standardfisch erben.
17
18 Der Preis des Fisches faellt linear je naeher der Spieler an die
19 Maximal-Grenze fuer Fisch kommt (Diese ist durch die Konstante MAX_FISH
20 festgelegt.) Der Master merkt sich ueber einen Zeitraum von FORGET_IT
21 Sekunden, dass der Spieler diesen Fisch gefangen hat. Ist der Zeitraum
22 vergangen, geht der Fisch nicht mehr in die Rechnung ein.
23 */
24
25#pragma strong_types, save_types, rtt_checks
26#pragma no_clone, no_shadow, no_inherit
27
28#define SAVE_FILE __DIR__+"save/fishes"
29
30#define FORGET_IT 1728000 // Nach 20 Tagen
31#define MAX_FISH 20000 // Wenn Spieler Max-Fish geholt hat, hat der
32 // Fisch keinen Wert mehr. (Einheit Gramm)
33
34#include <properties.h>
35
36// Hier wird gespeichert, welcher Spieler wieviel Fisch gefangen hat.
37mapping fishes = m_allocate(0,1);
38static int save_me_soon;
39
40protected void create() {
41 // Ohne das darf dieses Objekt hier nicht schreiben.
42 seteuid(getuid());
43 // Globale Variablen einlesen/initialisieren.
44 restore_object(SAVE_FILE);
45 set_next_reset(4*3600);
46}
47
48static void CleanupData() {
49 int expire_date = time()-FORGET_IT;
50 // Ueber alle Spielernamen laufen.
51 foreach(string pl, mixed *fishlist: fishes) {
52 // Ueber alle Fischdaten aller Spieler laufen.
53 foreach(int *fish: fishlist) {
54 if (fish[0]<expire_date) {
55 fishlist-=({fish});
56 save_me_soon=1;
57 }
58 }
59 if ( !sizeof(fishlist) )
60 fishes = m_delete(fishes, pl);
61 else
62 fishes += ([pl:fishlist]);
63 }
64}
65
66//ZZ: man koennte hier ggf. das neue Gewicht bestimmen statt es bei jedem
67//ZZ:Abruf zu tun.
68// Fuegt einen neuen Fisch in die Liste mit Fischen ein
69static int AddFish(string player_id, int weight) {
70 // Fisch hinzufuegen
71 if ( member(fishes, player_id) )
72 fishes[player_id] += ({({ time(),weight})});
73 else
74 fishes += ([ player_id: ({ ({time(),weight}) }) ]);
75 return 1;
76}
77
78// Hier wird das Gewicht des bereits gefangenen Fisches umgewandelt
79// in den Preis-Prozentsatz, den der Fisch noch kostet.
80static int WeightToPrice(int weight) {
81 if (weight >= MAX_FISH) return 0;
82 if (weight <= 0 ) return 100;
83 // Eine lineare Kurve. Je mehr Fisch geholt, desto billiger
84 // wird der. // Arathorn: Spannend, so eine lineare Kurve. :-)
85 return 100-(weight*100/MAX_FISH);
86}
87
88// Gibt das Gesamtgewicht des gefangenen Fisches zum Spieler zurueck
89static int QueryWeight(string player_id) {
90 int weight;
91 mixed list = fishes[player_id];
92
93 // Erstmal werden ungueltige Fische aus der Liste entfernt
94 //ZZ: ich finde, das muss nicht unbedingt bei jeden Abruf getan werden
95 //ZZ::und nicht fuer alle Spieler. reicht nicht einfach alle 4h?
96 CleanupData();
97
98 // Zusammenzaehlen der Einzelgewichte der gueltigen Fische.
99 foreach(int *fish : fishes[player_id]) {
100 weight += fish[1];
101 }
102 return weight;
103}
104
105// Wenn ein Spieler einen neuen Fisch bekommt, wird der Preis fuer den
106// Fisch bestimmt. Dieser resultiert aus der Menge (Gewicht) des Fisch,
107// die der Spieler in letzter Zeit schon gefangen hat. Zurueckgegeben
108// wird der Preis in Teilen von 100.
109public int PriceOfFish(object player, object fish) {
110 string player_id;
111 int price_of_new_fish;
112
113 // Sind Spieler und Fisch uebergeben?
114 if ( !player || !fish ) return 0;
115
116 // Spieler-ID finden.
117 player_id = getuuid(player);
118
119 // Ist player ein echter Spieler?
120 // NPC clonen sich Fische, die 100% kosten.
121 if (member(users(),player)==-1) return 100;
122
123 // Is der Fisch ein Fisch von Fraggle?
124 if (member(inherit_list(fish), __PATH__(1)+"/fish.c")==-1)
125 return 0;
126
127 // Feststellen wieviel Fisch ein Spieler gefangen hat, und
128 // daraus den Preis berechnen.
129 price_of_new_fish = WeightToPrice(QueryWeight(player_id));
130
131 // Diesen Fisch in die Datenbank eintragen
132 AddFish(player_id, fish->QueryProp(P_WEIGHT));
133
134 // Ich bin neugierig.
135 /*DEBUG(player->Name()+" hat einen Fisch mit "+fish->QueryProp(P_WEIGHT)+
136 " g gefangen. Der Wert liegt bei "+price_of_new_fish+"%");*/
137
138 // Die Aenderung soll persistent sein.
139 save_me_soon=1;
140
141 // Rueckgabe des Fischpreises.
142 return price_of_new_fish;
143}
144
145// Speichern der globalen Variablen
146static void save() {
147 save_object(SAVE_FILE);
148 return;
149}
150
151// Da nichts geerbt wird, muss das destruct() selbst gemacht werden
152// Wir speichern auf jeden Fall.
153varargs int remove(int silent) {
154 save();
155 destruct(this_object());
156 return 1;
157}
158
159// Daten aufraeumen und ggf. wegspeichern
160void reset() {
161 CleanupData();
162 if ( save_me_soon )
163 save();
164 set_next_reset(4*3600); // alle 4 Stunden reicht.
165}