Commit 67ee10e4 authored by Andy Castille's avatar Andy Castille
Browse files

foxes

parent fdc28462
from datetime import timedelta
from enum import Enum
from random import randint
from cou_server.common.geometry.point import Point
from cou_server.common.util import toast
from cou_server.entities.requirements import ItemRequirements, EnergyRequirements
from .. import NPC, SpriteSheet, Action, TRANSPARENT_SPRITE
placed_bait = dict() # Maps street names to lists of placed fox bait objects
SPAWN_TIME = timedelta(seconds=3)
SPEED_STOP = 0
SPEED_SLOW = 40
SPEED_FAST = 80
EAT_TIME = timedelta(seconds=3)
STINK_TIME = timedelta(minutes=5)
BRUSH_REQ = ItemRequirements()
BRUSH_REQ.any = ["fox_brush"]
BRUSH = Action("brush", "brushing")
BRUSH.energy_requirements = EnergyRequirements(3)
BRUSH.item_requirements = BRUSH_REQ
STATES = {
"brushed": SpriteSheet(
"brushed",
"https://childrenofur.com/assets/entityImages/orange_fox_brushed.png",
306,
139,
153,
139,
2,
True,
),
"eatEnd": SpriteSheet(
"eatEnd",
"https://childrenofur.com/assets/entityImages/orange_fox_eat_end.png",
765,
556,
153,
139,
20,
False,
),
"eatStart": SpriteSheet(
"eatStart",
"https://childrenofur.com/assets/entityImages/orange_fox_eat_start.png",
765,
278,
153,
139,
10,
False,
),
"eat": SpriteSheet(
"eat",
"https://childrenofur.com/assets/entityImages/orange_fox_eat.png",
765,
556,
153,
139,
20,
True,
),
"jump": SpriteSheet(
"jump",
"https://childrenofur.com/assets/entityImages/orange_fox_jump.png",
918,
695,
153,
139,
28,
False,
),
"pause": SpriteSheet(
"pause",
"https://childrenofur.com/assets/entityImages/orange_fox_pause.png",
918,
1390,
153,
139,
56,
False,
),
"run": SpriteSheet(
"run",
"https://childrenofur.com/assets/entityImages/orange_fox_run.png",
918,
278,
153,
139,
12,
True,
),
"taunt": SpriteSheet(
"taunt",
"https://childrenofur.com/assets/entityImages/orange_fox_taunt.png",
918,
973,
153,
139,
40,
False,
),
"walk": SpriteSheet(
"walk",
"https://childrenofur.com/assets/entityImages/orange_fox_walk.png",
918,
556,
153,
139,
24,
True,
),
"_hidden": TRANSPARENT_SPRITE,
}
SILVER_STATES = {
"brushed": SpriteSheet(
"brushed",
"https://childrenofur.com/assets/entityImages/silver_fox_brushed.png",
306,
139,
153,
139,
2,
True,
),
"eatEnd": SpriteSheet(
"eatEnd",
"https://childrenofur.com/assets/entityImages/silver_fox_eat_end.png",
765,
556,
153,
139,
20,
False,
),
"eatStart": SpriteSheet(
"eatStart",
"https://childrenofur.com/assets/entityImages/silver_fox_eat_start.png",
765,
278,
153,
139,
10,
False,
),
"eat": SpriteSheet(
"eat",
"https://childrenofur.com/assets/entityImages/silver_fox_eat.png",
765,
556,
153,
139,
20,
True,
),
"jump": SpriteSheet(
"jump",
"https://childrenofur.com/assets/entityImages/silver_fox_jump.png",
918,
695,
153,
139,
28,
False,
),
"pause": SpriteSheet(
"pause",
"https://childrenofur.com/assets/entityImages/silver_fox_pause.png",
918,
1390,
153,
139,
56,
False,
),
"run": SpriteSheet(
"run",
"https://childrenofur.com/assets/entityImages/silver_fox_run.png",
918,
278,
153,
139,
12,
True,
),
"taunt": SpriteSheet(
"taunt",
"https://childrenofur.com/assets/entityImages/silver_fox_taunt.png",
918,
973,
153,
139,
40,
False,
),
"walk": SpriteSheet(
"walk",
"https://childrenofur.com/assets/entityImages/silver_fox_walk.png",
918,
556,
153,
139,
24,
True,
),
"_hidden": TRANSPARENT_SPRITE,
}
BAIT_STATES = {
"stink1": SpriteSheet(
"stink1",
"https://childrenofur.com/assets/entityImages/fox_bait__x1_stink1_png_1354839629.png",
861,
288,
41,
144,
42,
True,
),
"stink2": SpriteSheet(
"stink1",
"https://childrenofur.com/assets/entityImages/fox_bait__x1_stink2_png_1354839630.png",
902,
288,
41,
144,
43,
True,
),
"stink3": SpriteSheet(
"stink1",
"https://childrenofur.com/assets/entityImages/fox_bait__x1_stink3_png_1354839632.png",
861,
288,
41,
144,
42,
True,
),
"_hidden": TRANSPARENT_SPRITE,
}
class FoxDestination(Enum):
NONE = 0
HOME = 1
BAIT = 2
class Fox(NPC):
last_state: SpriteSheet or None
despawning = False
waiting = False
brushing = False
destination_type = FoxDestination.NONE
moving_to: Point or None
home: Point
def __init__(self, entity_id, x, y, z, rotation, h_flip, street_name):
super().__init__(entity_id, x, y, z, rotation, h_flip, street_name)
self.type = "Fox"
self.speed = SPEED_STOP
self.facing_right = False
self.home = Point(0, 0)
self.hide()
def hide(self):
self.last_state = self.current_state
self.set_action_enabled(BRUSH.action_name, False)
self.set_state("_hidden")
def show(self, override_state: SpriteSheet):
state = override_state if override_state else self.last_state
if state:
self.set_state(state.state_name)
self.set_action_enabled(BRUSH.action_name, True)
self.last_state = None
def brush(self, user_socket=None, email: str = None) -> bool:
if randint(0, 1):
self.brushing = True
# TODO: await InventoryV2.decreaseDurability(email, BRUSH)
if not None:
# Could not use brush durability
self.brushing = False
return False
# TODO: await InventoryV2.addItemToUser(email, "fiber", 1)) != 1
if not None:
# Could not give user fiber
self.brushing = False
return False
toast("You got a fiber!", user_socket)
self.brushing = False
return True
else:
toast("The fox got away!", user_socket)
return False
def find_nearest_bait(self):
nearest = None
dist = None
for bait in placed_bait.get(self.street_name, list()):
dx = abs(self.x - bait.x)
dy = abs(self.y - bait.y)
db = dx ** 2 + dy ** 2
if nearest is None or db < dist:
nearest = bait
dist = db
return nearest
def update(self, simulate_tick: bool = False) -> None:
super().update(simulate_tick)
if self.waiting:
return
if self.brushing:
self.speed = SPEED_STOP
self.set_state("brushed")
return
if not self.moving_to:
# Find & target bait
nearest_bait = self.find_nearest_bait()
if nearest_bait and not nearest_bait.attracted_fox:
# Claim an unclaimed piece of bait
nearest_bait.attracted_fox = self
# Appear soon
self.waiting = True
# TODO: new Future.delayed(SPAWN_TIME).then((_) {
self.speed = SPEED_SLOW
self.show(self.states["walk"])
self.moving_to = Point(nearest_bait.x, nearest_bait.y)
self.destination_type = FoxDestination.BAIT
self.waiting = False
# TODO: }
elif not self.despawning:
# Disappear soon
self.despawning = True
# TODO: new Future.delayed(SPAWN_TIME).then((_) {
self.hide()
self.despawning = False
# TODO: }
else:
self.facing_right = self.moving_to.x > self.x
if abs(self.x - self.moving_to.x) < 20:
# At target
self.moving_to = None
if self.destination_type == FoxDestination.BAIT:
# Eat bait
self.speed = SPEED_STOP
self.set_state("eat")
self.waiting = True
self.find_nearest_bait().eat()
# Return to start position
self.speed = SPEED_FAST
self.set_state("run")
self.moving_to = self.home
self.destination_type = FoxDestination.HOME
elif self.destination_type == FoxDestination.HOME:
# Start over
self.hide()
# TODO: new Future.delayed(SPAWN_TIME).then((_) {
self.waiting = False
# TODO: });
else:
# Move toward target
if self.destination_type == FoxDestination.HOME:
self.speed = SPEED_FAST
self.set_state("run")
elif self.destination_type == FoxDestination.BAIT:
self.speed = SPEED_SLOW
self.set_state("walk")
self.move_xy()
class SilverFox(Fox):
def __init__(self, entity_id, x, y, z, rotation, h_flip, street_name):
super().__init__(entity_id, x, y, z, rotation, h_flip, street_name)
self.states = SILVER_STATES
self.hide()
class FoxBait(NPC):
attracted_fox: Fox or None
def __init__(self, entity_id, x, y, z, rotation, h_flip, street_name):
super().__init__(entity_id, x, y, z, rotation, h_flip, street_name)
self.type = "Fox Bait"
self.speed = 0
# Mark bait as placed on this street
if self.street_name not in placed_bait:
placed_bait[street_name] = list()
placed_bait[street_name] += [self]
self.states = BAIT_STATES
self.set_state(f"stink{randint(1, 3)}")
# Add to street
# TODO: StreetUpdateHandler.streets[streetName]?.npcs[this.id] = this;
# Go away after a while if left uneaten
# TODO: new Future.delayed(MAX_TIME).then((_) => eat());
def update(self, simulate_tick: bool = False) -> None:
super().update(simulate_tick)
# Fall to platforms
self.move_xy()
def eat(self):
# TODO: await new Future.delayed(EAT_TIME);
self.set_state("_hidden")
# TODO: StreetUpdateHandler.streets[streetName].npcs.remove(id);
self.attracted_fox = None
def __str__(self):
return f"Fox bait at ({self.x}, {self.y})"
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment