Housekeeping

This commit is contained in:
KeepBotting
2019-03-26 14:05:40 -04:00
parent a0c78ced90
commit 739c331860
135 changed files with 4 additions and 4 deletions
@@ -0,0 +1,20 @@
require 'java'
java_import 'org.apollo.game.model.entity.Mob'
module MobExtension
MOB_EXTENSIONS = []
def self.register(extension)
fail 'Provided extension object is not a module' unless extension.is_a?(Module)
new_mixins = extension.public_instance_methods
current_mixins = MOB_EXTENSIONS.map { |e| {e.to_s => e.public_instance_methods} }
current_mixins.each do |ext, methods|
methods.each {|m| fail "Extension #{ext} already provides method #{m}" if new_mixins.include?(m) }
end
Mob.include(extension)
end
end
@@ -0,0 +1,15 @@
<?xml version="1.0"?>
<plugin>
<id>mob-extension</id>
<version>0.1</version>
<name>Mob Extensions</name>
<description>Adds support for extending Mobs with new functionality</description>
<authors>
<author>Gary Tierney</author>
</authors>
<scripts>
<script>extension.rb</script>
</scripts>
<dependencies>
</dependencies>
</plugin>
+58
View File
@@ -0,0 +1,58 @@
on :message, :walk do |player, msg|
player.reset_interacting_mob
end
on :message, :player_action do |player, msg|
## todo: need a better way of mapping option numbers to their purpose
player.follow($world.player_repository.get(msg.index)) if msg.option == 3
end
##
# A <code>MobExtension</code> for making a <code>Mob</code> trail behind, or chase a given mob.
module FollowingMobExtension
##
# Follow a mob and trail behind them.
def follow(mob)
do_follow(self, mob, behind: true)
end
##
# Chase a mob (with the intention of getting in front of them), also optionally
# stopping within a projectile distance when at a position where a projectile can
# reach the target.
def chase(mob, projectile_distance: nil)
do_follow(self, mob, front: true, projectile_distance: projectile_distance)
end
end
MobExtension::register(FollowingMobExtension)
private
def do_follow(source, mob, behind: false, front: false, projectile_distance: nil)
source.interacting_mob = mob
schedule 0, true do |task|
# stop the task unless we're still interacting with the other mob.
unless self.interacting_mob.eql? mob
task.stop
next
end
next unless source.walking_queue.size <= 1
distance = mob.position.get_distance(source.position)
unless projectile_distance.nil?
next if distance <= projectile_distance &&
$world.collision_manager.raycast(source.position, mob.position)
end
if distance > 15
reset_interacting_mob
end
walk_to(mob, behind: behind, front: front)
end
end
+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<plugin>
<id>mob-following</id>
<version>1</version>
<name>Following</name>
<description>Adds following for mobs.</description>
<authors>
<author>Steve Soltys</author>
</authors>
<scripts>
<script>following.rb</script>
</scripts>
<dependencies>
<dependency>mob-walk-to</dependency>
</dependencies>
</plugin>
@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<plugin>
<id>mob-walk-to</id>
<version>0.1</version>
<name>Mob path generation</name>
<description>Adds a mixin for making mobs walk to another entity.</description>
<authors>
<author>Gary Tierney</author>
</authors>
<scripts>
<script>walk_to.rb</script>
</scripts>
<dependencies>
<dependency>mob-extension</dependency>
</dependencies>
</plugin>
@@ -0,0 +1,83 @@
java_import 'org.apollo.game.model.entity.path.AStarPathfindingAlgorithm'
java_import 'org.apollo.game.model.entity.path.EuclideanHeuristic'
java_import 'org.apollo.game.model.entity.path.SimplePathfindingAlgorithm'
java_import 'org.apollo.game.model.entity.obj.GameObject'
java_import 'org.apollo.game.model.entity.Mob'
java_import 'org.apollo.game.model.entity.Player'
java_import 'org.apollo.game.model.entity.EntityType'
java_import 'org.apollo.game.model.Direction'
##
# A pathfinder used for simple following (i.e.: An NPC attacking a player).
SIMPLE_PATH_FINDER = SimplePathfindingAlgorithm.new($world.collision_manager)
##
# A pathfinder used for precise following (i.e.: A player attacking another player).
FOLLOW_PATH_FINDER = AStarPathfindingAlgorithm.new($world.collision_manager, EuclideanHeuristic.new)
##
# The directions that we use as a random offset when not walking to the facing direction.
OFFSET_DIRECTIONS = Direction::NESW.to_a
module WalkToMobExtension
def walk_to(entity, front: false, behind: false)
if [front, behind].count { |option| option == true } > 1
fail 'Can only specify one of "front" or "behind"'
end
position = self.position
target_position = entity.position
target_distance = position.get_distance(target_position)
target_offset = walk_to_offset(entity)
target_offset_direction = OFFSET_DIRECTIONS.sample
target_facing_direction = walk_to_facing_direction(entity)
unless target_facing_direction.nil?
if front
target_offset_direction = target_facing_direction
elsif behind
target_offset_direction = target_facing_direction.opposite
end
end
target_offset_position = target_position.step(target_offset, target_offset_direction)
return if target_offset_position.eql?(position)
pathfinder = FOLLOW_PATH_FINDER
path = pathfinder.find(position, target_offset_position)
path.each { |tile| self.walking_queue.add_step(tile) }
end
end
MobExtension::register(WalkToMobExtension)
private
##
# Gets the number of tiles away from an entity's actual origin that we can
# walk to.
def walk_to_offset(entity)
case entity.entity_type
when EntityType::DYNAMIC_OBJECT, EntityType::STATIC_OBJECT
return max(entity.definition.width, entity.definition.length) + 1
when EntityType::NPC
return entity.definition.size + 1
when EntityType::PLAYER
return 1
else
fail "walk_to_offset called with invalid entity type: #{type.to_s}"
end
end
##
# Gets the direction that an entity is facing, so a mob can walk up infront of them.
def walk_to_facing_direction(entity)
case entity.entity_type
when EntityType::DYNAMIC_OBJECT, EntityType::STATIC_OBJECT
return Direction::WNES[entity.orientation]
when EntityType::NPC, EntityType::PLAYER
return entity.last_direction
else
fail "walk_to_offset called with invalid entity type: #{type.to_s}"
end
end