diff options
author | proller <proller@github.com> | 2013-07-27 22:34:30 +0400 |
---|---|---|
committer | proller <proller@github.com> | 2013-07-27 23:21:48 +0400 |
commit | 3aedfac9685c2d9ae8bac5a5b7e72e527f22c08d (patch) | |
tree | d1f9067040acb0b5dad42a2ae8935b91124a36d3 /src/content_abm.cpp | |
parent | e65d8ad6553d7ae0acf63b43e9818059088a00b6 (diff) | |
download | minetest-3aedfac9685c2d9ae8bac5a5b7e72e527f22c08d.tar.gz minetest-3aedfac9685c2d9ae8bac5a5b7e72e527f22c08d.tar.bz2 minetest-3aedfac9685c2d9ae8bac5a5b7e72e527f22c08d.zip |
Weather support
Diffstat (limited to 'src/content_abm.cpp')
-rw-r--r-- | src/content_abm.cpp | 274 |
1 files changed, 205 insertions, 69 deletions
diff --git a/src/content_abm.cpp b/src/content_abm.cpp index 6adcbf708..110ac1eea 100644 --- a/src/content_abm.cpp +++ b/src/content_abm.cpp @@ -28,6 +28,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "treegen.h" // For treegen::make_tree #include "main.h" // for g_settings #include "map.h" +#include "cpp_api/scriptapi.h" +#include "log.h" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" @@ -166,86 +168,220 @@ public: } }; -class LiquidFlowABM : public ActiveBlockModifier -{ -private: - std::set<std::string> contents; +class LiquidFlowABM : public ActiveBlockModifier { + private: + std::set<std::string> contents; -public: - LiquidFlowABM(ServerEnvironment *env, INodeDefManager *nodemgr) - { - std::set<content_t> liquids; - nodemgr->getIds("group:liquid", liquids); - for(std::set<content_t>::const_iterator k = liquids.begin(); k != liquids.end(); k++) - contents.insert(nodemgr->get(*k).liquid_alternative_flowing); - - } - virtual std::set<std::string> getTriggerContents() - { - return contents; - } - virtual float getTriggerInterval() - { return 10.0; } - virtual u32 getTriggerChance() - { return 10; } - virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) - { - ServerMap *map = &env->getServerMap(); - if (map->transforming_liquid_size() > 500) - return; - map->transforming_liquid_add(p); - //if ((*map).m_transforming_liquid.size() < 500) (*map).m_transforming_liquid.push_back(p); - } + public: + LiquidFlowABM(ServerEnvironment *env, INodeDefManager *nodemgr) { + std::set<content_t> liquids; + nodemgr->getIds("group:liquid", liquids); + for(std::set<content_t>::const_iterator k = liquids.begin(); k != liquids.end(); k++) + contents.insert(nodemgr->get(*k).liquid_alternative_flowing); + } + virtual std::set<std::string> getTriggerContents() { + return contents; + } + virtual float getTriggerInterval() + { return 10.0; } + virtual u32 getTriggerChance() + { return 10; } + virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) { + ServerMap *map = &env->getServerMap(); + if (map->transforming_liquid_size() > 500) + return; + map->transforming_liquid_add(p); + } }; -class LiquidDropABM : public ActiveBlockModifier -{ -private: - std::set<std::string> contents; +class LiquidDropABM : public ActiveBlockModifier { + private: + std::set<std::string> contents; -public: - LiquidDropABM(ServerEnvironment *env, INodeDefManager *nodemgr) - { - std::set<content_t> liquids; - nodemgr->getIds("group:liquid", liquids); - for(std::set<content_t>::const_iterator k = liquids.begin(); k != liquids.end(); k++) - contents.insert(nodemgr->get(*k).liquid_alternative_source); - } - virtual std::set<std::string> getTriggerContents() - { return contents; } - virtual std::set<std::string> getRequiredNeighbors() - { - std::set<std::string> neighbors; - neighbors.insert("mapgen_air"); - return neighbors; - } - virtual float getTriggerInterval() - { return 20.0; } - virtual u32 getTriggerChance() - { return 10; } - virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) - { - ServerMap *map = &env->getServerMap(); - if (map->transforming_liquid_size() > 500) - return; - if ( map->getNodeNoEx(p - v3s16(0, 1, 0 )).getContent() != CONTENT_AIR // below - && map->getNodeNoEx(p - v3s16(1, 0, 0 )).getContent() != CONTENT_AIR // right - && map->getNodeNoEx(p - v3s16(-1, 0, 0 )).getContent() != CONTENT_AIR // left - && map->getNodeNoEx(p - v3s16(0, 0, 1 )).getContent() != CONTENT_AIR // back - && map->getNodeNoEx(p - v3s16(0, 0, -1)).getContent() != CONTENT_AIR // front - ) - return; - map->transforming_liquid_add(p); - } + public: + LiquidDropABM(ServerEnvironment *env, INodeDefManager *nodemgr) { + std::set<content_t> liquids; + nodemgr->getIds("group:liquid", liquids); + for(std::set<content_t>::const_iterator k = liquids.begin(); k != liquids.end(); k++) + contents.insert(nodemgr->get(*k).liquid_alternative_source); + } + virtual std::set<std::string> getTriggerContents() + { return contents; } + virtual std::set<std::string> getRequiredNeighbors() { + std::set<std::string> neighbors; + neighbors.insert("mapgen_air"); + return neighbors; + } + virtual float getTriggerInterval() + { return 20.0; } + virtual u32 getTriggerChance() + { return 10; } + virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) { + ServerMap *map = &env->getServerMap(); + if (map->transforming_liquid_size() > 500) + return; + if ( map->getNodeNoEx(p - v3s16(0, 1, 0 )).getContent() != CONTENT_AIR // below + && map->getNodeNoEx(p - v3s16(1, 0, 0 )).getContent() != CONTENT_AIR // right + && map->getNodeNoEx(p - v3s16(-1, 0, 0 )).getContent() != CONTENT_AIR // left + && map->getNodeNoEx(p - v3s16(0, 0, 1 )).getContent() != CONTENT_AIR // back + && map->getNodeNoEx(p - v3s16(0, 0, -1)).getContent() != CONTENT_AIR // front + ) + return; + map->transforming_liquid_add(p); + } }; -void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef) -{ +class LiquidFreeze : public ActiveBlockModifier { + public: + LiquidFreeze(ServerEnvironment *env, INodeDefManager *nodemgr) { } + virtual std::set<std::string> getTriggerContents() { + std::set<std::string> s; + s.insert("group:freezes"); + return s; + } + virtual std::set<std::string> getRequiredNeighbors() { + std::set<std::string> s; + s.insert("mapgen_air"); + s.insert("group:melts"); + return s; + } + virtual float getTriggerInterval() + { return 10.0; } + virtual u32 getTriggerChance() + { return 20; } + virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) { + ServerMap *map = &env->getServerMap(); + INodeDefManager *ndef = env->getGameDef()->ndef(); + + float heat = map->getHeat(env, p); + //heater = rare + if (heat <= -1 && (heat <= -50 || ((myrand_range(-50, heat)) <= -30))) { + content_t c_self = n.getContent(); + // making freeze not annoying, do not freeze random blocks in center of ocean + // todo: any block not water (dont freeze _source near _flowing) + content_t c; + bool allow = heat < -40; + // todo: make for(...) + if (!allow) { + c = map->getNodeNoEx(p - v3s16(0, 1, 0 )).getContent(); // below + if (c == CONTENT_AIR || c == CONTENT_IGNORE) + return; // do not freeze when falling + if (c != c_self && c != CONTENT_IGNORE) allow = 1; + if (!allow) { + c = map->getNodeNoEx(p - v3s16(1, 0, 0 )).getContent(); // right + if (c != c_self && c != CONTENT_IGNORE) allow = 1; + if (!allow) { + c = map->getNodeNoEx(p - v3s16(-1, 0, 0 )).getContent(); // left + if (c != c_self && c != CONTENT_IGNORE) allow = 1; + if (!allow) { + c = map->getNodeNoEx(p - v3s16(0, 0, 1 )).getContent(); // back + if (c != c_self && c != CONTENT_IGNORE) allow = 1; + if (!allow) { + c = map->getNodeNoEx(p - v3s16(0, 0, -1)).getContent(); // front + if (c != c_self && c != CONTENT_IGNORE) allow = 1; + } + } + } + } + } + if (allow) { + n.setContent(ndef->getId(ndef->get(n).freezemelt)); + map->addNodeWithEvent(p, n); + } + } + } +}; + +class LiquidMeltWeather : public ActiveBlockModifier { + public: + LiquidMeltWeather(ServerEnvironment *env, INodeDefManager *nodemgr) { } + virtual std::set<std::string> getTriggerContents() { + std::set<std::string> s; + s.insert("group:melts"); + return s; + } + virtual std::set<std::string> getRequiredNeighbors() { + std::set<std::string> s; + s.insert("mapgen_air"); + s.insert("group:freezes"); + return s; + } + virtual float getTriggerInterval() + { return 10.0; } + virtual u32 getTriggerChance() + { return 20; } + virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) { + ServerMap *map = &env->getServerMap(); + INodeDefManager *ndef = env->getGameDef()->ndef(); + + float heat = map->getHeat(env, p); + if (heat >= 1 && (heat >= 40 || ((myrand_range(heat, 40)) >= 20))) { + n.setContent(ndef->getId(ndef->get(n).freezemelt)); + if (!n.getLevel(ndef)) + n.addLevel(ndef); + map->addNodeWithEvent(p, n); + env->getScriptIface()->node_falling_update(p); + } + } +}; + +class LiquidMeltHot : public ActiveBlockModifier { + public: + LiquidMeltHot(ServerEnvironment *env, INodeDefManager *nodemgr) { } + virtual std::set<std::string> getTriggerContents() { + std::set<std::string> s; + s.insert("group:melts"); + return s; + } + virtual std::set<std::string> getRequiredNeighbors() { + std::set<std::string> s; + s.insert("group:igniter"); + s.insert("group:hot"); + return s; + } + virtual float getTriggerInterval() + { return 2.0; } + virtual u32 getTriggerChance() + { return 4; } + virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) { + ServerMap *map = &env->getServerMap(); + INodeDefManager *ndef = env->getGameDef()->ndef(); + n.setContent(ndef->getId(ndef->get(n).freezemelt)); + if (!n.getLevel(ndef)) + n.addLevel(ndef); + map->addNodeWithEvent(p, n); + env->getScriptIface()->node_falling_update(p); + } +}; + +class LiquidMeltAround : public LiquidMeltHot { + public: + LiquidMeltAround(ServerEnvironment *env, INodeDefManager *nodemgr) + : LiquidMeltHot(env, nodemgr) { } + virtual std::set<std::string> getRequiredNeighbors() { + std::set<std::string> s; + s.insert("group:melt_around"); + return s; + } + virtual float getTriggerInterval() + { return 40.0; } + virtual u32 getTriggerChance() + { return 60; } +}; + + +void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef) { env->addActiveBlockModifier(new GrowGrassABM()); env->addActiveBlockModifier(new RemoveGrassABM()); env->addActiveBlockModifier(new MakeTreesFromSaplingsABM(env, nodedef)); if (g_settings->getBool("liquid_finite")) { env->addActiveBlockModifier(new LiquidFlowABM(env, nodedef)); env->addActiveBlockModifier(new LiquidDropABM(env, nodedef)); + env->addActiveBlockModifier(new LiquidMeltHot(env, nodedef)); + env->addActiveBlockModifier(new LiquidMeltAround(env, nodedef)); + if (g_settings->getBool("weather")) { + env->addActiveBlockModifier(new LiquidFreeze(env, nodedef)); + env->addActiveBlockModifier(new LiquidMeltWeather(env, nodedef)); + } } } |