]> git.lizzy.rs Git - minetest-m13.git/blob - src/content_abm.cpp
Update to 4.6 base
[minetest-m13.git] / src / content_abm.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "content_abm.h"
21
22 #include "environment.h"
23 #include "gamedef.h"
24 #include "nodedef.h"
25 #include "content_sao.h"
26 #include "settings.h"
27 #include "mapblock.h" // For getNodeBlockPos
28 #include "mapgen.h" // For mapgen::make_tree
29
30 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
31
32 class GrowGrassABM : public ActiveBlockModifier
33 {
34 private:
35 public:
36         virtual std::set<std::string> getTriggerContents()
37         {
38                 std::set<std::string> s;
39                 s.insert("dirt");
40                 return s;
41         }
42         virtual float getTriggerInterval()
43         { return 2.0; }
44         virtual u32 getTriggerChance()
45         { return 200; }
46         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n)
47         {
48                 INodeDefManager *ndef = env->getGameDef()->ndef();
49                 ServerMap *map = &env->getServerMap();
50                 
51                 MapNode n_top = map->getNodeNoEx(p+v3s16(0,1,0));
52                 if(ndef->get(n_top).light_propagates &&
53                                 !ndef->get(n_top).isLiquid() &&
54                                 n_top.getLightBlend(env->getDayNightRatio(), ndef) >= 13)
55                 {
56                         n.setContent(ndef->getId("dirt_with_grass"));
57                         map->addNodeWithEvent(p, n);
58                 }
59         }
60 };
61
62 class RemoveGrassABM : public ActiveBlockModifier
63 {
64 private:
65 public:
66         virtual std::set<std::string> getTriggerContents()
67         {
68                 std::set<std::string> s;
69                 s.insert("dirt_with_grass");
70                 return s;
71         }
72         virtual float getTriggerInterval()
73         { return 2.0; }
74         virtual u32 getTriggerChance()
75         { return 20; }
76         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n)
77         {
78                 INodeDefManager *ndef = env->getGameDef()->ndef();
79                 ServerMap *map = &env->getServerMap();
80                 
81                 MapNode n_top = map->getNodeNoEx(p+v3s16(0,1,0));
82                 if(!ndef->get(n_top).light_propagates ||
83                                 ndef->get(n_top).isLiquid())
84                 {
85                         n.setContent(ndef->getId("dirt"));
86                         map->addNodeWithEvent(p, n);
87                 }
88         }
89 };
90
91 class SpawnRatsAroundTreesABM : public ActiveBlockModifier
92 {
93 private:
94 public:
95         virtual std::set<std::string> getTriggerContents()
96         {
97                 std::set<std::string> s;
98                 s.insert("tree");
99                 s.insert("jungletree");
100                 return s;
101         }
102         virtual float getTriggerInterval()
103         { return 10.0; }
104         virtual u32 getTriggerChance()
105         { return 200; }
106         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
107                         u32 active_object_count, u32 active_object_count_wider)
108         {
109                 if(active_object_count_wider != 0)
110                         return;
111
112                 INodeDefManager *ndef = env->getGameDef()->ndef();
113                 ServerMap *map = &env->getServerMap();
114                 
115                 v3s16 p1 = p + v3s16(myrand_range(-2, 2),
116                                 0, myrand_range(-2, 2));
117                 MapNode n1 = map->getNodeNoEx(p1);
118                 MapNode n1b = map->getNodeNoEx(p1+v3s16(0,-1,0));
119                 if(n1b.getContent() == ndef->getId("dirt_with_grass") &&
120                                 n1.getContent() == CONTENT_AIR)
121                 {
122                         v3f pos = intToFloat(p1, BS);
123                         ServerActiveObject *obj = new RatSAO(env, pos);
124                         env->addActiveObject(obj);
125                 }
126         }
127 };
128
129 static void getMob_dungeon_master(Settings &properties)
130 {
131         properties.set("looks", "dungeon_master");
132         properties.setFloat("yaw", 1.57);
133         properties.setFloat("hp", 30);
134         properties.setBool("bright_shooting", true);
135         properties.set("shoot_type", "fireball");
136         properties.set("shoot_y", "0.7");
137         properties.set("player_hit_damage", "1");
138         properties.set("player_hit_distance", "1.0");
139         properties.set("player_hit_interval", "0.5");
140         properties.setBool("mindless_rage", myrand_range(0,100)==0);
141 }
142
143 class SpawnInCavesABM : public ActiveBlockModifier
144 {
145 private:
146 public:
147         virtual std::set<std::string> getTriggerContents()
148         {
149                 std::set<std::string> s;
150                 s.insert("stone");
151                 s.insert("mossycobble");
152                 return s;
153         }
154         virtual float getTriggerInterval()
155         { return 2.0; }
156         virtual u32 getTriggerChance()
157         { return 1000; }
158         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
159                         u32 active_object_count, u32 active_object_count_wider)
160         {
161                 if(active_object_count_wider != 0)
162                         return;
163
164                 INodeDefManager *ndef = env->getGameDef()->ndef();
165                 ServerMap *map = &env->getServerMap();
166
167                 v3s16 p1 = p + v3s16(0,1,0);
168                 MapNode n1a = map->getNodeNoEx(p1+v3s16(0,0,0));
169                 if(n1a.getLightBlend(env->getDayNightRatio(), ndef) <= 3){
170                         MapNode n1b = map->getNodeNoEx(p1+v3s16(0,1,0));
171                         if(n1a.getContent() == CONTENT_AIR &&
172                                         n1b.getContent() == CONTENT_AIR)
173                         {
174                                 v3f pos = intToFloat(p1, BS);
175                                 int i = myrand()%5;
176                                 if(i == 0 || i == 1){
177                                         actionstream<<"A dungeon master spawns at "
178                                                         <<PP(p1)<<std::endl;
179                                         Settings properties;
180                                         getMob_dungeon_master(properties);
181                                         ServerActiveObject *obj = new MobV2SAO(
182                                                         env, pos, &properties);
183                                         env->addActiveObject(obj);
184                                 } else if(i == 2 || i == 3){
185                                         actionstream<<"Rats spawn at "
186                                                         <<PP(p1)<<std::endl;
187                                         for(int j=0; j<3; j++){
188                                                 ServerActiveObject *obj = new RatSAO(
189                                                                 env, pos);
190                                                 env->addActiveObject(obj);
191                                         }
192                                 } else {
193                                         actionstream<<"An oerkki spawns at "
194                                                         <<PP(p1)<<std::endl;
195                                         ServerActiveObject *obj = new Oerkki1SAO(
196                                                         env, pos);
197                                         env->addActiveObject(obj);
198                                 }
199                         }
200                 }
201         }
202 };
203
204 class MakeTreesFromSaplingsABM : public ActiveBlockModifier
205 {
206 private:
207 public:
208         virtual std::set<std::string> getTriggerContents()
209         {
210                 std::set<std::string> s;
211                 s.insert("sapling");
212                 return s;
213         }
214         virtual float getTriggerInterval()
215         { return 10.0; }
216         virtual u32 getTriggerChance()
217         { return 50; }
218         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
219                         u32 active_object_count, u32 active_object_count_wider)
220         {
221                 INodeDefManager *ndef = env->getGameDef()->ndef();
222                 ServerMap *map = &env->getServerMap();
223                 
224                 actionstream<<"A sapling grows into a tree at "
225                                 <<PP(p)<<std::endl;
226
227                 core::map<v3s16, MapBlock*> modified_blocks;
228                 v3s16 tree_p = p;
229                 ManualMapVoxelManipulator vmanip(map);
230                 v3s16 tree_blockp = getNodeBlockPos(tree_p);
231                 vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1));
232                 bool is_apple_tree = myrand()%4 == 0;
233                 mapgen::make_tree(vmanip, tree_p, is_apple_tree, ndef);
234                 vmanip.blitBackAll(&modified_blocks);
235
236                 // update lighting
237                 core::map<v3s16, MapBlock*> lighting_modified_blocks;
238                 for(core::map<v3s16, MapBlock*>::Iterator
239                         i = modified_blocks.getIterator();
240                         i.atEnd() == false; i++)
241                 {
242                         lighting_modified_blocks.insert(i.getNode()->getKey(), i.getNode()->getValue());
243                 }
244                 map->updateLighting(lighting_modified_blocks, modified_blocks);
245
246                 // Send a MEET_OTHER event
247                 MapEditEvent event;
248                 event.type = MEET_OTHER;
249                 for(core::map<v3s16, MapBlock*>::Iterator
250                         i = modified_blocks.getIterator();
251                         i.atEnd() == false; i++)
252                 {
253                         v3s16 p = i.getNode()->getKey();
254                         event.modified_blocks.insert(p, true);
255                 }
256                 map->dispatchEvent(&event);
257         }
258 };
259
260 void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef)
261 {
262         env->addActiveBlockModifier(new GrowGrassABM());
263         env->addActiveBlockModifier(new RemoveGrassABM());
264         env->addActiveBlockModifier(new SpawnRatsAroundTreesABM());
265         env->addActiveBlockModifier(new SpawnInCavesABM());
266         env->addActiveBlockModifier(new MakeTreesFromSaplingsABM());
267 }
268
269