diff --git a/components/Characters/KukeChild.tscn b/components/Characters/KukeChild.tscn new file mode 100644 index 0000000..5126795 --- /dev/null +++ b/components/Characters/KukeChild.tscn @@ -0,0 +1,37 @@ +[gd_scene load_steps=5 format=3 uid="uid://c5q7djx12phem"] + +[ext_resource type="PackedScene" uid="uid://cvogxi7mktumf" path="res://components/Abstracts/EntityBase.tscn" id="1_3ohuq"] +[ext_resource type="Texture2D" uid="uid://lorraj4pe2lt" path="res://resources/characters/kukechild/KukeChild.png" id="2_7vbs6"] +[ext_resource type="Script" path="res://scripts/Contents/Characters/KukeChild.gd" id="2_ywxbd"] + +[sub_resource type="SpriteFrames" id="SpriteFrames_5rcbd"] +animations = [{ +"frames": [{ +"duration": 1.0, +"texture": ExtResource("2_7vbs6") +}], +"loop": true, +"name": &"idle", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": ExtResource("2_7vbs6") +}], +"loop": true, +"name": &"walk", +"speed": 5.0 +}] + +[node name="KukeChild" instance=ExtResource("1_3ohuq")] +script = ExtResource("2_ywxbd") + +[node name="texture" parent="." index="2"] +sprite_frames = SubResource("SpriteFrames_5rcbd") +animation = &"walk" + +[node name="normal" type="Node2D" parent="texture/weapons" index="0"] +position = Vector2(47, 11) + +[node name="statebar" parent="." index="3"] +position = Vector2(0, -125) diff --git a/components/Characters/KukeMC.tscn b/components/Characters/KukeMC.tscn index 15484c5..a47b4ee 100644 --- a/components/Characters/KukeMC.tscn +++ b/components/Characters/KukeMC.tscn @@ -38,6 +38,7 @@ animation = &"walk" shape = SubResource("RectangleShape2D_farlp") [node name="normal" type="Node2D" parent="texture/weapons" index="0"] +position = Vector2(-22, 18) [node name="statebar" parent="." index="3"] position = Vector2(0, -140) diff --git a/resources/characters/kukechild/KukeChild.png b/resources/characters/kukechild/KukeChild.png new file mode 100644 index 0000000..a69c6c7 Binary files /dev/null and b/resources/characters/kukechild/KukeChild.png differ diff --git a/resources/characters/kukechild/KukeChild.png.import b/resources/characters/kukechild/KukeChild.png.import new file mode 100644 index 0000000..f19073d --- /dev/null +++ b/resources/characters/kukechild/KukeChild.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://lorraj4pe2lt" +path="res://.godot/imported/KukeChild.png-4ca0607e1c4594e36fa458519a8a0756.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resources/characters/kukechild/KukeChild.png" +dest_files=["res://.godot/imported/KukeChild.png-4ca0607e1c4594e36fa458519a8a0756.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/scripts/Contents/Characters/KukeChild.gd b/scripts/Contents/Characters/KukeChild.gd new file mode 100644 index 0000000..2fb3138 --- /dev/null +++ b/scripts/Contents/Characters/KukeChild.gd @@ -0,0 +1,21 @@ +extends EntityBase + +var masterMine: KukeMC + +func register(): + fields[FieldStore.Entity.MAX_HEALTH] = 25 + fields[FieldStore.Entity.OFFSET_SHOOT] = 2 + fields[FieldStore.Entity.MOVEMENT_SPEED] = 0.25 + fields[FieldStore.Entity.DAMAGE_MULTIPILER] = 0.1 + attackCooldownMap[0] = 200 +func ai(): + PresetEntityAI.follow(self, currentFocusedBoss, 500) + tryAttack(0) + if timeLived() > 10000: + masterMine.tryHeal(100) + tryDie(null) +func attack(type): + if type == 0: + for i in randi_range(1, 3): + BulletBase.generate(preload("res://components/Bullets/PurpleCrystal.tscn"), self, findWeaponAnchor("normal"), position.angle_to_point(currentFocusedBoss.position)) + await TickTool.millseconds(randi_range(5, 25)) diff --git a/scripts/Contents/Characters/KukeMC.gd b/scripts/Contents/Characters/KukeMC.gd index aa1c51f..9aa6dd0 100644 --- a/scripts/Contents/Characters/KukeMC.gd +++ b/scripts/Contents/Characters/KukeMC.gd @@ -1,10 +1,12 @@ extends EntityBase class_name KukeMC + func register(): - fields[FieldStore.Entity.MAX_HEALTH] = 2500 - fields[FieldStore.Entity.OFFSET_SHOOT] = 15 + fields[FieldStore.Entity.MAX_HEALTH] = 3500 + fields[FieldStore.Entity.OFFSET_SHOOT] = 25 fields[FieldStore.Entity.MOVEMENT_SPEED] = 0.5 - attackCooldownMap[0] = 2000 + attackCooldownMap[0] = 8000 + attackCooldownMap[1] = 5000 func ai(): PresetEntityAI.follow(self, currentFocusedBoss, 500) for bullet in get_tree().get_nodes_in_group("bullets"): @@ -13,9 +15,15 @@ func ai(): bullet.position.distance_to(self.position) < 200 # 酷可mc会去摧毁200半径以内的七彩飞星 ): bullet.tryDestroy() - tryAttack(0) + for i in len(attackCooldownMap.keys()): + tryAttack(i) func attack(type): if type == 0: for i in randi_range(8, 16): BulletBase.generate(preload("res://components/Bullets/PurpleCrystal.tscn"), self, findWeaponAnchor("normal"), position.angle_to_point(currentFocusedBoss.position)) await TickTool.millseconds(randi_range(10, 50)) + elif type == 1: + for i in randi_range(1, 2): + var child = EntityBase.generate(preload("res://components/Characters/KukeChild.tscn"), position + MathTool.randv2_range(500)) + child.currentFocusedBoss = currentFocusedBoss + child.masterMine = self diff --git a/scripts/Contents/Characters/Rooster.gd b/scripts/Contents/Characters/Rooster.gd index 8290dca..0850646 100644 --- a/scripts/Contents/Characters/Rooster.gd +++ b/scripts/Contents/Characters/Rooster.gd @@ -33,7 +33,3 @@ func sprint(): Input.get_axis("m_left", "m_right"), Input.get_axis("m_up", "m_down") ) * sprintMultiplier, true) -func heal(count: float): - health += count - DamageLabel.create(-count, false, damageAnchor.global_position + MathTool.randv2_range(GameRule.damageLabelSpawnOffset)) - return count diff --git a/scripts/Statemachine/EntityBase.gd b/scripts/Statemachine/EntityBase.gd index 8b0edfc..8535fc4 100644 --- a/scripts/Statemachine/EntityBase.gd +++ b/scripts/Statemachine/EntityBase.gd @@ -96,8 +96,10 @@ var charginup: bool = false var weapons: Array[Weapon] = [] var canRunAi: bool = true var currentStage: int = 0 +var spawnTime: float = 0 func _ready(): + spawnTime = WorldManager.getTime() register() var selfStatebar: EntityStateBar = $"%statebar" if isBoss: @@ -166,6 +168,8 @@ func _physics_process(_delta: float) -> void: trailParticle.emitting = trailing # 通用方法 +func timeLived(): + return WorldManager.getTime() - spawnTime func setStage(stage: int): if currentStage == stage: return @@ -284,30 +288,32 @@ func sprintTo(target: Vector2, speed: float): position = target trailing = false targetableSprinting = false -func tryDie(by: BulletBase): +func tryDie(by: BulletBase = null): if is_queued_for_deletion(): return - for drop in range(min(len(drops), len(dropCounts))): - var item = drops[drop] - var count = ceil(randf_range(dropCounts[drop].x, dropCounts[drop].y)) - for i in range(count): - ItemDropped.generate(item, randi_range(1, int(sqrt(count) + GameRule.difficulty)), position + MathTool.randv2_range(GameRule.itemDroppedSpawnOffset)) - if MathTool.rate( - GameRule.appleDropRate + - by.launcher.fields.get(FieldStore.Entity.DROP_APPLE_RATE) + - GameRule.appleDropRateInfluenceByLuckValue * by.launcher.fields[FieldStore.Entity.LUCK_VALUE] - ) or isBoss: - for i in randi_range(appleCount.x, appleCount.y): - ItemDropped.generate(ItemStore.ItemType.APPLE, 1, position + MathTool.randv2_range(GameRule.itemDroppedSpawnOffset)) - ItemDropped.generate( - ItemStore.ItemType.BEACHBALL, - fields[FieldStore.Entity.MAX_HEALTH] * randf_range(1 - GameRule.beachballOffset, 1 + GameRule.beachballOffset), - position + MathTool.randv2_range(GameRule.itemDroppedSpawnOffset) - ) - if isPlayer(): - if UIState.player == self: - UIState.setPanel("GameOver", [displayName, by.launcher.displayName, by.displayName]) + if is_instance_valid(by): + for drop in range(min(len(drops), len(dropCounts))): + var item = drops[drop] + var count = ceil(randf_range(dropCounts[drop].x, dropCounts[drop].y)) + for i in range(count): + ItemDropped.generate(item, randi_range(1, int(sqrt(count) + GameRule.difficulty)), position + MathTool.randv2_range(GameRule.itemDroppedSpawnOffset)) + if MathTool.rate( + GameRule.appleDropRate + + by.launcher.fields.get(FieldStore.Entity.DROP_APPLE_RATE) + + GameRule.appleDropRateInfluenceByLuckValue * by.launcher.fields[FieldStore.Entity.LUCK_VALUE] + ) or isBoss: + for i in randi_range(appleCount.x, appleCount.y): + ItemDropped.generate(ItemStore.ItemType.APPLE, 1, position + MathTool.randv2_range(GameRule.itemDroppedSpawnOffset)) + ItemDropped.generate( + ItemStore.ItemType.BEACHBALL, + fields[FieldStore.Entity.MAX_HEALTH] * randf_range(1 - GameRule.beachballOffset, 1 + GameRule.beachballOffset), + position + MathTool.randv2_range(GameRule.itemDroppedSpawnOffset) + ) + if isPlayer(): + if UIState.player == self: + UIState.setPanel("GameOver", [displayName, by.launcher.displayName, by.displayName]) EffectController.create(preload("res://components/Effects/DeadBlood.tscn"), texture.global_position).shot() await die() + queue_free() func tryHeal(count: float): if inventory[ItemStore.ItemType.APPLE] > 0 and health < fields.get(FieldStore.Entity.MAX_HEALTH): inventory[ItemStore.ItemType.APPLE] -= 1 @@ -347,11 +353,12 @@ func ai(): func attack(_type: int): pass func die(): - queue_free() + pass func sprint(): pass func heal(count: float): health += count + DamageLabel.create(-count, false, damageAnchor.global_position + MathTool.randv2_range(GameRule.damageLabelSpawnOffset)) return count func register(): pass