Cow_Life_Sim_RPG/Player/Cow.gd

594 lines
17 KiB
GDScript

extends CharacterBody2D
class_name Cow
signal moved
var interactionsInRange = []
var targetInteraction
var interactionTrigger
var cowState = "Idle"
var currentInteractingItem
var currentInteractingGroundItem
var interactingSpeed
var currentInteractingBuildingZone
var interactionTimer = 0
var interactionState = "none"
var lastInteractionCheckThreshold = 100
var movementTarget:Vector2
var movementThreshold = 0.1
var moveSpeed:int = 200
var fastWalking = false
var swimmingZones = []
var soakTimer = 2
var facingLeft:bool = true
var defaultVisiblesPosition
var lastPosition
var pointsForXpDrop = 100
var movementXpProgress = 0
var movementXpAmount = 5
var timeMovedMultiplier = 10
var distanceMovedMultiplier = 0.1
var maxMovementThresholdForXP = 50
var wisdom = []
var wisdomDelays = []
var wisdomTimer = 0
var wisdomIndex = 0
var rng = RandomNumberGenerator.new()
func _ready():
defaultVisiblesPosition = %Visuals.position
fastWalking = false
movementTarget = position
lastPosition = position
face_direction(false)
func _process(delta):
if !cowState == "Riding":
if targetInteraction != null:
if target_interaction_range_check():
movementTarget = global_position
else:
movement(delta)
else:
movement(delta)
if cowState == "Drinking":
drinking(delta)
if cowState == "Weaving":
weaving(delta)
if cowState == "Building":
building(delta)
if cowState == "Playing":
playing(delta)
if cowState == "Demolishing":
demolishing(delta)
if interactionTimer > 0:
interactionTimer -= delta
if interactionTimer <= 0:
if cowState == "Eating":
if currentInteractingItem.get_name(false).contains("Brass Key"):
juice_consultant_location_wisdom()
LevelManager.get_skill("appreciating").experience_item(currentInteractingItem, "ate")
InventoryManager.remove_item_from_inventory(currentInteractingItem)
AchievementManager.eat_achievement_checks(currentInteractingItem)
if currentInteractingItem.get_edibility() >= 125:
AchievementManager.complete_achievement("Delicious Delicacy")
stop_eating()
change_state("Idle")
if wisdomTimer > 0:
wisdomTimer -= delta
if wisdomTimer <= 0:
MessageManager.addMessage(wisdom[wisdomIndex], GameVariables.player, "Cow", Color.YELLOW)
wisdomIndex += 1
if wisdomIndex < wisdom.size():
wisdomTimer = wisdomDelays[wisdomIndex - 1]
func juice_consultant_location_wisdom():
get_tree().get_root().get_node("MainGame/PuzzleCompleteAudio").play()
wisdomIndex = 0
wisdomTimer = 0.1
wisdom = ["Upon a circle ever spinning", "I must board a creature ever buzzing",
"Upon them I must shout with glee:", "Yippee!"]
wisdomDelays = [4.1, 4.1, 4.1]
SaveManager.set_save_value("juiceKnowledgeObtained", true)
func change_state(targetState):
if cowState == "Drinking":
stop_drinking()
if cowState == "Eating":
stop_eating()
if cowState == "Playing":
stop_playing()
if cowState == "Beholding":
stop_beholding()
if cowState == "Weaving":
stop_weaving()
if cowState == "Building":
stop_building()
if cowState == "Demolishing":
stop_demolishing()
cowState = targetState
if cowState == "Idle":
play_animation("Idle")
func reset_visuals_pos():
%Visuals.position = defaultVisiblesPosition
func set_visuals_pos(newPosition):
%Visuals.position = newPosition
func add_swimming_area(swimmingArea):
swimmingZones.append(swimmingArea)
func remove_swimming_area(swimmingArea):
swimmingZones.erase(swimmingArea)
func clear_swimming_areas():
swimmingZones = []
soakTimer = 0.2
%Waves.visible = false
moveSpeed = 200
func playing(delta):
if currentInteractingItem.get_name(false) == "DIY Excavation":
if %Toy.frame >= 2 and interactionState == "started":
interactionState = "boneShown"
InventoryManager.remove_item_from_inventory(currentInteractingItem)
var boneReward = BoneGenerator.get_a_bone()
InventoryManager.add_item_to_inventory(boneReward)
var xpReward = BoneGenerator.get_xp_reward_for_bone(boneReward)
LevelManager.add_XP("gaming", xpReward)
%Bone.visible = true
%Bone.texture = boneReward.get_sprite()
if %Toy.frame >= 5 and interactionState == "boneShown":
interactionState = "done"
%Toy.pause()
func behold_item(item):
change_state("Beholding")
play_animation("Playing")
%BeheldItem.visible = true
currentInteractingItem = item
var itemAnimation:SpriteFrames = SpriteFrames.new()
itemAnimation.add_frame("default", item.get_sprite())
%BeheldItem.sprite_frames = itemAnimation
%BeheldItem.frame = 0
AchievementManager.behold_achievement_checks(item)
LevelManager.get_skill("appreciating").experience_item(currentInteractingItem, "beholded")
GlobalEvents.itemBeheld.emit(item)
func stop_beholding():
%BeheldItem.visible = false
func play_item(item):
if item.get_name(false) == "Ball":
var newBall = preload("res://Objects/Beach/Ball/Ball.tscn").instantiate()
newBall.global_position = global_position + Vector2(rng.randf_range(-50, 50), rng.randf_range(-5, 5))
LocationManager.currentLocation.add_child(newBall)
AchievementManager.play_achievement_checks(item)
LevelManager.get_skill("appreciating").experience_item(item, "played")
GlobalEvents.itemPlayedWith.emit(item)
InventoryManager.remove_item_from_inventory(item)
return
change_state("Playing")
play_animation("Playing")
%Toy.visible = true
currentInteractingItem = item
interactionState = "started"
var itemAnimation:SpriteFrames = SpriteFrames.new()
for additionalSprite in item.get_additional_sprites():
itemAnimation.add_frame("default", additionalSprite)
%Toy.sprite_frames = itemAnimation
%Toy.frame = 0
%Toy.play()
AchievementManager.play_achievement_checks(item)
LevelManager.get_skill("appreciating").experience_item(currentInteractingItem, "played")
GlobalEvents.itemPlayedWith.emit(item)
func stop_playing():
%Toy.visible = false
%Bone.visible = false
func eat_item(item):
play_animation("Eat")
change_state("Eating")
%Food.visible = true
%Food.texture = item.get_sprite()
currentInteractingItem = item
interactionTimer = 1.5
func stop_eating():
%Food.visible = false
func demolish(buildingZone):
change_state("Demolishing")
play_animation("Idle")
currentInteractingBuildingZone = buildingZone
var demolishingBar:ProgressBar = %DemolishingBar
demolishingBar.visible = true
demolishingBar.value = 0
interactingSpeed = buildingZone.get_demolishing_speed()
func demolishing(delta):
%DemolishingBar.value += interactingSpeed * delta
if %DemolishingBar.value >= 100:
%DemolishingBar.value = 0
currentInteractingBuildingZone.demolished()
change_state("Idle")
func stop_demolishing():
%DemolishingBar.visible = false
func build(item, buildingZone):
change_state("Building")
play_animation("Idle")
currentInteractingItem = item
currentInteractingBuildingZone = buildingZone
var buildingBar:ProgressBar = %BuildingBar
buildingBar.visible = true
buildingBar.value = 0
var itemColor = SpriteGeneration.get_average_color(item.get_sprite().get_image(), [Color.BLACK])
var buildingBarStyleBox:StyleBoxFlat = StyleBoxFlat.new()
buildingBarStyleBox.set_border_width_all(2)
buildingBarStyleBox.set_corner_radius_all(6)
buildingBarStyleBox.border_color = Color.TRANSPARENT
buildingBarStyleBox.bg_color = itemColor
buildingBarStyleBox.anti_aliasing = false
buildingBar.set("theme_override_styles/fill", buildingBarStyleBox)
interactingSpeed = LevelManager.get_skill("building").get_building_speed(item)
lastInteractionCheckThreshold = rng.randi_range(20, 80)
func stop_building():
%BuildingBar.visible = false
func building(delta):
%BuildingBar.value += interactingSpeed * delta
if !InventoryManager.check_if_in_inventory(currentInteractingItem):
change_state("Idle")
var itemName = currentInteractingItem.get_name()
MessageManager.addMessage("i need more " + itemName, GameVariables.player, "Cow", Color.YELLOW)
return
if %BuildingBar.value >= 100:
InventoryManager.spend_item(currentInteractingItem)
%BuildingBar.value = 0
lastInteractionCheckThreshold = rng.randi_range(20, 80)
if !currentInteractingBuildingZone.stage_complete():
change_state("Idle")
elif %BuildingBar.value >= lastInteractionCheckThreshold:
var successChance = currentInteractingBuildingZone.get_success_chance(currentInteractingItem)
if rng.randi_range(0, 100) > successChance:
MessageManager.addMessage("dam", GameVariables.player, "Cow", Color.YELLOW)
%BuildingBar.value = 0
lastInteractionCheckThreshold = rng.randi_range(20, 80)
InventoryManager.spend_item(currentInteractingItem)
LevelManager.add_XP("building", 1)
else:
lastInteractionCheckThreshold = 200
func weave_item(item):
change_state("Weaving")
play_animation("Idle")
currentInteractingItem = item
var weavingBar:ProgressBar = %WeavingBar
weavingBar.visible = true
weavingBar.value = 0
var basketColor = SpriteGeneration.get_average_color(item.get_sprite().get_image(), [Color.BLACK])
var weavingBarStyleBox:StyleBoxFlat = StyleBoxFlat.new()
weavingBarStyleBox.set_border_width_all(2)
weavingBarStyleBox.set_corner_radius_all(6)
weavingBarStyleBox.border_color = Color.TRANSPARENT
weavingBarStyleBox.bg_color = basketColor
weavingBarStyleBox.anti_aliasing = false
weavingBar.set("theme_override_styles/fill", weavingBarStyleBox)
interactingSpeed = LevelManager.get_skill("basketWeaving").get_basketing_speed(item)
lastInteractionCheckThreshold = 0
func stop_weaving():
%WeavingBar.visible = false
if %WeavingBar.value >= 50 and %WeavingBar.value < 100:
currentInteractingItem.set_modification(Item.modifications.Knotted)
currentInteractingGroundItem.set_item(currentInteractingItem)
LevelManager.add_XP("basketWeaving", LevelManager.get_skill("basketWeaving").get_failed_item_xp(currentInteractingItem))
func drink_juice(item):
play_animation("Drink")
change_state("Drinking")
%Juice.visible = true
%Juice.texture = item.get_sprite()
currentInteractingItem = item
var juiceBar:ProgressBar = %JuiceBar
var juiceColor = SpriteGeneration.get_average_color(%Juice.texture.get_image(), [Color.BLACK])
var juiceBarStyleBox:StyleBoxFlat = StyleBoxFlat.new()
juiceBarStyleBox.set_border_width_all(2)
juiceBarStyleBox.set_corner_radius_all(6)
juiceBarStyleBox.border_color = Color.TRANSPARENT
juiceBarStyleBox.bg_color = juiceColor
juiceBarStyleBox.anti_aliasing = false
juiceBar.set("theme_override_styles/fill", juiceBarStyleBox)
%JuiceBar.value = 100
%JuiceBar.visible = true
%JuiceParticles.emitting = true
%JuiceParticles.visible = true
%JuiceParticles.position.x = 65
%JuiceParticles.color = juiceColor
interactingSpeed = LevelManager.get_skill("juiceDrinking").get_drink_speed(item)
lastInteractionCheckThreshold = 100
func stop_drinking():
%Juice.visible = false
%JuiceBar.visible = false
%JuiceParticles.emitting = false
%JuiceParticles.visible = false
%JuiceParticles.restart()
func drinking(delta):
%JuiceBar.value -= interactingSpeed * delta
%JuiceParticles.position.x = 57 - (130*((100 - %JuiceBar.value)*0.01))
if %JuiceBar.value <= 0:
if currentInteractingItem.get_name(false).contains("Brass Key"):
juice_consultant_location_wisdom()
InventoryManager.remove_item_from_inventory(currentInteractingItem)
if currentInteractingItem.get_name(false) == "Green Soda":
var newItem = preload("res://Items/Foods/Liquids/GreenSodaCan.gd").new()
InventoryManager.add_item_to_inventory(newItem)
elif currentInteractingItem.get_name(false) == "Blue Soda":
var newItem = preload("res://Items/Foods/Liquids/BlueSodaCan.gd").new()
InventoryManager.add_item_to_inventory(newItem)
elif currentInteractingItem.get_name(false).contains("Brass Key"):
juice_consultant_location_wisdom()
AchievementManager.drink_achievement_checks(currentInteractingItem)
LevelManager.add_XP("juiceDrinking", LevelManager.get_skill("juiceDrinking").get_item_xp(currentInteractingItem))
LevelManager.get_skill("appreciating").experience_item(currentInteractingItem, "drank")
change_state("Idle")
elif %JuiceBar.value <= (lastInteractionCheckThreshold - 20):
var blehChance = LevelManager.get_skill("juiceDrinking").get_bleh_chance(currentInteractingItem)
if rng.randi_range(0, 100) <= blehChance:
MessageManager.addMessage("bleh", GameVariables.player, "Cow", Color.YELLOW)
change_state("Idle")
lastInteractionCheckThreshold -= 20
func weaving(delta):
%WeavingBar.value += interactingSpeed * delta
if %WeavingBar.value >= 100:
GlobalEvents.itemWeaved.emit(currentInteractingItem)
var newBasket = BasketGenerator.generate_basket(currentInteractingItem)
currentInteractingGroundItem.set_item(newBasket)
LevelManager.add_XP("basketWeaving", LevelManager.get_skill("basketWeaving").get_item_xp(currentInteractingItem))
LevelManager.get_skill("appreciating").experience_item(newBasket, "wove")
change_state("Idle")
elif %WeavingBar.value >= (lastInteractionCheckThreshold + 20):
var failChance = LevelManager.get_skill("basketWeaving").get_fail_chance(currentInteractingItem)
if rng.randi_range(0, 100) <= failChance:
MessageManager.addMessage("oh deer", GameVariables.player, "Cow", Color.YELLOW)
change_state("Idle")
lastInteractionCheckThreshold += 20
func set_target_position(targetPos):
movementTarget = targetPos
if movementTarget.x != global_position.x:
if movementTarget.x > global_position.x:
face_direction(false)
else:
face_direction(true)
moved.emit()
func movement(delta):
if swimmingZones.size() > 0:
soakTimer -= delta
if soakTimer <= 0:
soakTimer = 2
InventoryManager.soak_player_inventory()
if !%Waves.visible:
%Waves.visible = true
$Splash.play()
%WaterSpray.emitting = true
var mainSwimmingZone = swimmingZones[0]
for zone in swimmingZones:
if zone.swimmingSpeed <= mainSwimmingZone.swimmingSpeed:
mainSwimmingZone = zone
%Waves.self_modulate = mainSwimmingZone.liquidColor
moveSpeed = mainSwimmingZone.swimmingSpeed
var swimmingLevel = LevelManager.get_skill("swimming").currentLevel
moveSpeed = mainSwimmingZone.swimmingSpeed * (1 + (0.015 * swimmingLevel))
else:
soakTimer = 0.2
%Waves.visible = false
moveSpeed = 200
if fastWalking:
moveSpeed += 40
moveSpeed += LevelManager.get_skill("fastWalking").currentLevel * 1.5
var distanceToTarget = global_position.distance_to(movementTarget)
if distanceToTarget > movementThreshold:
handle_movement_xp(delta, (lastPosition - position).length())
lastPosition = position
var movementVector = global_position.move_toward(movementTarget, moveSpeed*delta) - global_position
velocity = movementVector
var collision = move_and_collide(velocity)
if collision:
velocity = velocity.slide(collision.get_normal())
handle_collision(collision)
play_animation("Walk")
change_state("Walking")
elif cowState == "Walking":
global_position = movementTarget
play_animation("Idle")
change_state("Idle")
func handle_collision(collision:KinematicCollision2D):
var collider = collision.get_collider()
if collider is NoSwimBlocker:
collider.cow_collided()
func handle_movement_xp(time, distance):
if distance > maxMovementThresholdForXP:
return
var xpToEarn = 0
movementXpProgress += (time * timeMovedMultiplier)
movementXpProgress += (distance * distanceMovedMultiplier)
while movementXpProgress >= pointsForXpDrop:
if swimmingZones.size() > 0:
var mainSwimmingZone = swimmingZones[0]
for zone in swimmingZones:
if zone.swimmingSpeed <= mainSwimmingZone.swimmingSpeed:
mainSwimmingZone = zone
xpToEarn += mainSwimmingZone.swimmingXp
else:
xpToEarn += movementXpAmount
movementXpProgress -= pointsForXpDrop
if xpToEarn > 0:
if swimmingZones.size() > 0:
LevelManager.add_XP("swimming", xpToEarn)
elif fastWalking:
LevelManager.add_XP("fastWalking", xpToEarn)
else:
LevelManager.add_XP("walking", xpToEarn)
func interact(interactionObj, interactionFunction, interactionPosition):
targetInteraction = interactionObj
interactionTrigger = interactionFunction
set_target_position(interactionPosition)
func target_interaction_range_check():
if targetInteraction in interactionsInRange:
interactionTrigger.call()
targetInteraction = null
return true
return false
func _on_interaction_area_area_entered(area):
if area.get_parent() is Interaction:
interactionsInRange.append(area.get_parent())
func _on_interaction_area_area_exited(area):
if area.get_parent() is Interaction:
if area.get_parent() in interactionsInRange:
interactionsInRange.erase(area.get_parent())
func face_direction(left:bool = true):
if left:
if !facingLeft:
facingLeft = true
%Cow.flip_h = false
%Cow.position.x -= 37
%Juice.position.x = -74
%Toy.flip_h = false
%Toy.position.x = -72
%Bone.flip_h = false
%Bone.position.x = -72
%Food.flip_h = false
%Food.position.x = -74
%BeheldItem.position.x = -69
else:
if facingLeft:
facingLeft = false
%Cow.flip_h = true
%Cow.position.x += 37
%Juice.position.x = 74
%Toy.flip_h = true
%Toy.position.x = 72
%Bone.flip_h = true
%Bone.position.x = 72
%Food.flip_h = true
%Food.position.x = 74
%BeheldItem.position.x = 69
func play_animation(animationName):
%Cow.play(animationName)
func _on_cow_animation_finished():
play_animation("Idle")