diff --git a/components/Bullets/MagicMissle.tscn b/components/Bullets/MagicMissle.tscn new file mode 100644 index 0000000..b550b51 --- /dev/null +++ b/components/Bullets/MagicMissle.tscn @@ -0,0 +1,65 @@ +[gd_scene format=3 uid="uid://db2jwaqphd1cx"] + +[ext_resource type="PackedScene" uid="uid://crtdkysmnkith" path="res://components/Abstracts/BulletBase.tscn" id="1_4sjx4"] +[ext_resource type="Script" uid="uid://b1y8r5xrhhso" path="res://scripts/Contents/Bullets/MagicMissle.gd" id="2_lrw10"] +[ext_resource type="Texture2D" uid="uid://bl1i26ovfpxwc" path="res://resources/bullets/magic-missle/tr.webp" id="2_ross6"] +[ext_resource type="Texture2D" uid="uid://drikpnrvqisb0" path="res://resources/bullets/magic-missle/ninesols.png" id="2_rugh7"] + +[sub_resource type="Curve" id="Curve_lrw10"] +_data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(0.2, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] +point_count = 3 + +[sub_resource type="CurveTexture" id="CurveTexture_3jny5"] +curve = SubResource("Curve_lrw10") + +[sub_resource type="Curve" id="Curve_grb5l"] +_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] +point_count = 2 + +[sub_resource type="CurveTexture" id="CurveTexture_jigkj"] +curve = SubResource("Curve_grb5l") + +[sub_resource type="Curve" id="Curve_rugh7"] +_data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(0.2, 1), 0.0, 0.0, 0, 0] +point_count = 2 + +[sub_resource type="CurveTexture" id="CurveTexture_lrw10"] +curve = SubResource("Curve_rugh7") + +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_mgg76"] +particle_flag_disable_z = true +angle_min = 1.0728835e-05 +angle_max = 360.00003 +angle_curve = SubResource("CurveTexture_jigkj") +direction = Vector3(-1, 0, 0) +spread = 15.0 +initial_velocity_min = 100.0 +initial_velocity_max = 200.0 +gravity = Vector3(0, 0, 0) +scale_min = 0.5 +scale_max = 0.9 +scale_curve = SubResource("CurveTexture_lrw10") +alpha_curve = SubResource("CurveTexture_3jny5") + +[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_rugh7"] +height = 76.0 + +[node name="MagicMissle" unique_id=5571707 instance=ExtResource("1_4sjx4")] +script = ExtResource("2_lrw10") +penerate = 1.0 +penerateDamageReduction = 0.1 + +[node name="static" type="Sprite2D" parent="texture" parent_id_path=PackedInt32Array(162977358) index="2" unique_id=1008850333] +texture = ExtResource("2_rugh7") + +[node name="trail" type="GPUParticles2D" parent="texture/static" index="0" unique_id=1403224943] +z_index = -1 +position = Vector2(-35, 1) +amount = 50 +texture = ExtResource("2_ross6") +visibility_rect = Rect2(-1000, -1000, 2000, 2000) +process_material = SubResource("ParticleProcessMaterial_mgg76") + +[node name="hitbox" parent="." index="1" unique_id=175349408] +rotation = 1.5707964 +shape = SubResource("CapsuleShape2D_rugh7") diff --git a/components/Characters/Rooster.tscn b/components/Characters/Rooster.tscn index 22c7646..b816c8c 100644 --- a/components/Characters/Rooster.tscn +++ b/components/Characters/Rooster.tscn @@ -2,11 +2,9 @@ [ext_resource type="PackedScene" uid="uid://cvogxi7mktumf" path="res://components/Abstracts/EntityBase.tscn" id="1_e5pl8"] [ext_resource type="Script" uid="uid://cthtupc6dtbav" path="res://scripts/Contents/Characters/Rooster.gd" id="2_oqdqd"] -[ext_resource type="PackedScene" uid="uid://c0n3igy4hucrg" path="res://components/Weapons/PurpleCrystal.tscn" id="3_joj4g"] +[ext_resource type="PackedScene" uid="uid://c6d23yqjhe0ju" path="res://components/Weapons/MagicMissle.tscn" id="3_da2ca"] [ext_resource type="AudioStream" uid="uid://cdrevrq7n6yqa" path="res://resources/sounds/effect/Boing.mp3" id="4_66s6c"] -[ext_resource type="PackedScene" uid="uid://cx7nogfnv7s8t" path="res://components/Weapons/Tree.tscn" id="4_jluqw"] [ext_resource type="AudioStream" uid="uid://benyec5bqni0b" path="res://resources/sounds/effect/Chomp.wav" id="4_k0yme"] -[ext_resource type="PackedScene" uid="uid://dyanyf044boxp" path="res://components/Weapons/Pipe.tscn" id="5_fkh3f"] [ext_resource type="AudioStream" uid="uid://dmxh3bpk8vyy5" path="res://resources/sounds/effect/Coin.mp3" id="5_xnbhq"] [ext_resource type="AudioStream" uid="uid://4wuuf1osk0yv" path="res://resources/sounds/effect/Low Boing.wav" id="6_m5px1"] [ext_resource type="Texture2D" uid="uid://fn8qx72clh38" path="res://resources/characters/cock/rooster-a.svg" id="8_da2ca"] @@ -103,13 +101,9 @@ process_material = SubResource("ParticleProcessMaterial_joj4g") [node name="weaponStore" parent="." index="2"] process_mode = 4 -[node name="PurpleCrystal" parent="weaponStore" index="0" unique_id=1478939386 instance=ExtResource("3_joj4g")] +[node name="MagicMissle" parent="weaponStore" index="0" unique_id=2085048785 instance=ExtResource("3_da2ca")] debugRebuild = false -[node name="Tree" parent="weaponStore" index="1" unique_id=185228402 instance=ExtResource("4_jluqw")] - -[node name="Pipe" parent="weaponStore" index="2" unique_id=946948425 instance=ExtResource("5_fkh3f")] - [node name="sprint" parent="sounds" index="0"] stream = ExtResource("4_66s6c") diff --git a/components/Weapons/MagicMissle.tscn b/components/Weapons/MagicMissle.tscn index 0ddb16e..356c687 100644 --- a/components/Weapons/MagicMissle.tscn +++ b/components/Weapons/MagicMissle.tscn @@ -2,13 +2,16 @@ [ext_resource type="PackedScene" uid="uid://ckq2cq6m23hq3" path="res://components/Abstracts/WeaponCardBase.tscn" id="1_c3bm3"] [ext_resource type="Texture2D" uid="uid://dce1da2qm24pb" path="res://resources/weapons/magic-missle.webp" id="2_3sdrm"] +[ext_resource type="Script" uid="uid://clec7nrtesipu" path="res://scripts/Contents/Weapons/MagicMissle.gd" id="2_r857c"] [node name="MagicMissle" unique_id=2085048785 instance=ExtResource("1_c3bm3")] +script = ExtResource("2_r857c") avatarTexture = ExtResource("2_3sdrm") displayName = "导弹法杖" +emitType = 3 store = { "G": 197392.0, -"atk": 14, +"atk": 10, "count": 3.0, "cursor-m": 100.0, "missle-m": 10.0, @@ -23,14 +26,15 @@ storeType = { "track": 0 } descriptionTemplate = "召唤1~$count枚[b]魔法导弹[/b],围绕鼠标指针做由鼠标指针提供向心力的圆周运动。 -鼠标指针质量:$cursor-m, -魔法导弹质量:$missle-m, -初始轨道半径:$track, +鼠标指针质量:$cursor-mkg, +魔法导弹质量:$missle-mkg, +初始轨道半径:$trackm, 万有引力常数:$G。 魔法导弹碰撞时造成$atk点伤害, 分裂出$count枚[b]次级导弹[/b], 可继承分裂最多$count次。" sources = Array[String](["万有引力", "宇宙航行"]) +cooldown = 1000.0 debugRebuild = true [node name="avatar" parent="container/info" parent_id_path=PackedInt32Array(1625294072) index="0" unique_id=1021985889] @@ -44,11 +48,11 @@ text = "万有引力 × 宇宙航行" [node name="description" parent="container" parent_id_path=PackedInt32Array(575698869) index="2" unique_id=566230682] text = "[center]召唤1~[color=cyan]3[/color]枚[b]魔法导弹[/b],围绕鼠标指针做由鼠标指针提供向心力的圆周运动。 -鼠标指针质量:[color=cyan]100.00[/color], -魔法导弹质量:[color=cyan]10.00[/color], -初始轨道半径:[color=cyan]200.00[/color], +鼠标指针质量:[color=cyan]100.00[/color]kg, +魔法导弹质量:[color=cyan]10.00[/color]kg, +初始轨道半径:[color=cyan]200.00[/color]m, 万有引力常数:[color=cyan]197392[/color]。 -魔法导弹碰撞时造成[color=cyan]14[/color]点伤害, +魔法导弹碰撞时造成[color=cyan]10[/color]点伤害, 分裂出[color=cyan]3[/color]枚[b]次级导弹[/b], 可继承分裂最多[color=cyan]3[/color]次。[/center]" diff --git a/resources/bullets/magic-missle/ninesols.png b/resources/bullets/magic-missle/ninesols.png index 3e3bb22..79feed0 100644 Binary files a/resources/bullets/magic-missle/ninesols.png and b/resources/bullets/magic-missle/ninesols.png differ diff --git a/scripts/Contents/Bullets/MagicMissle.gd b/scripts/Contents/Bullets/MagicMissle.gd new file mode 100644 index 0000000..157abf4 --- /dev/null +++ b/scripts/Contents/Bullets/MagicMissle.gd @@ -0,0 +1,34 @@ +extends BulletBase +class_name MagicMissleBullet + +var powerScale: int = 3 +var speedV2: Vector2 = Vector2.ZERO +var accelerating: bool = true +var roundBullets: Array[MagicMissleBullet] + +func ai(): + if accelerating: + rotation = lerp_angle(rotation, position.angle_to_point(get_global_mouse_position()), 0.1) + speedV2 += (get_global_mouse_position() - position).normalized() * 1 + elif speed < 1: + tryDestroy() + speedV2 *= 0.995 + speed = speedV2.length() + PresetBulletAI.forward(self , speedV2.angle()) + +func succeedToHit(_dmg: float, entity: EntityBase): + if powerScale > 0 && accelerating && roundBullets.count(self ) > 0: + for i in randi_range(1, powerScale): + for bullet in BulletBase.generate( + ComponentManager.getBullet("MagicMissle"), + launcher, + position, + entity.position.angle_to_point(position) + PI + randf_range(-1, 1) * deg_to_rad(60) + ): + if bullet is MagicMissleBullet: + bullet.position += Vector2.from_angle(bullet.rotation) * 100 + bullet.speedV2 += Vector2.from_angle(bullet.rotation) * 30 + bullet.roundBullets = roundBullets + bullet.powerScale = powerScale - 1 + roundBullets.append(bullet) + powerScale = 0 diff --git a/scripts/Contents/Bullets/MagicMissle.gd.uid b/scripts/Contents/Bullets/MagicMissle.gd.uid new file mode 100644 index 0000000..db49d28 --- /dev/null +++ b/scripts/Contents/Bullets/MagicMissle.gd.uid @@ -0,0 +1 @@ +uid://b1y8r5xrhhso diff --git a/scripts/Contents/Characters/Rooster.gd b/scripts/Contents/Characters/Rooster.gd index a588584..5c2e0e9 100644 --- a/scripts/Contents/Characters/Rooster.gd +++ b/scripts/Contents/Characters/Rooster.gd @@ -54,24 +54,26 @@ func tryLaunch(action: String, weaponIndex: int): chargeStartTime[weaponIndex] = Time.get_ticks_msec() chargeParticle.emitting = true chargeParticle.speed_scale = 1 - elif weapon.emitType == Weapon.EmitType.CLICK_SHOOT: + elif weapon.emitType == Weapon.EmitType.CLICK_SHOOT || weapon.emitType == Weapon.EmitType.HOLD_LOOP: tryAttack(weaponIndex) if Input.is_action_pressed(action): if len(weapons) > weaponIndex: var weapon = weapons[weaponIndex] if chargeStartTime.has(weaponIndex): chargeParticle.speed_scale += 0.01 * self.fields.get(FieldStore.Entity.CHARGE_SPEED) - elif weapon.emitType == Weapon.EmitType.HOLD_SHOOT: + elif weapon.emitType == Weapon.EmitType.HOLD_SHOOT || weapon.emitType == Weapon.EmitType.HOLD_LOOP: tryAttack(weaponIndex) if Input.is_action_just_released(action): - if chargeStartTime.has(weaponIndex): - var startTime = chargeStartTime[weaponIndex] - var endTime = Time.get_ticks_msec() - var chargedTime = endTime - startTime - chargeStartTime.erase(weaponIndex) - if len(weapons) > weaponIndex: - var weapon = weapons[weaponIndex] - if weapon.emitType == Weapon.EmitType.CHARGE: + if len(weapons) > weaponIndex: + var weapon = weapons[weaponIndex] + if weapon.emitType == Weapon.EmitType.CHARGE: + if chargeStartTime.has(weaponIndex): + var startTime = chargeStartTime[weaponIndex] + var endTime = Time.get_ticks_msec() + var chargedTime = endTime - startTime + chargeStartTime.erase(weaponIndex) weapon.chargedTime = chargedTime * self.fields.get(FieldStore.Entity.CHARGE_SPEED) tryAttack(weaponIndex) chargeParticle.emitting = false + elif weapon.emitType == Weapon.EmitType.HOLD_LOOP: + weapon.exitLoop(self ) diff --git a/scripts/Contents/Weapons/MagicMissle.gd b/scripts/Contents/Weapons/MagicMissle.gd new file mode 100644 index 0000000..24153ea --- /dev/null +++ b/scripts/Contents/Weapons/MagicMissle.gd @@ -0,0 +1,36 @@ +@tool +extends Weapon + +var roundBullets: Array[MagicMissleBullet] = [] + +func update(to: int, origin: Dictionary, _entity: EntityBase): + origin["atk"] += 1 * to * soulLevel + origin["cursor-m"] += 0.2 * to * soulLevel + origin["missle-m"] += 0.02 * to * soulLevel + origin["track"] += 1 * to * soulLevel + origin["G"] *= 1.25 ** (soulLevel - 1) + origin["count"] += 1 * (soulLevel - 1) + return origin + +func loopStart(entity: EntityBase): + for i in randi_range(1, readStore("count")): + for bullet in BulletBase.generate( + ComponentManager.getBullet("MagicMissle"), + entity, + get_global_mouse_position() + Vector2.from_angle(randf_range(0, 2 * PI)) * readStore("track"), + 0 + ): + if bullet is MagicMissleBullet: + bullet.look_at(get_global_mouse_position()) + bullet.rotation += PI / 2 + bullet.speedV2 += Vector2.from_angle(bullet.rotation) * sqrt((readStore("G") * readStore("cursor-m") / readStore("track") ** 2) * readStore("track")) / 120 + bullet.roundBullets = roundBullets + bullet.baseDamage = readStore("atk") + bullet.powerScale = readStore("count") + roundBullets.append(bullet) + return true +func loopExit(_entity: EntityBase): + for bullet in roundBullets: + if is_instance_valid(bullet): + bullet.accelerating = false + roundBullets.clear() diff --git a/scripts/Contents/Weapons/MagicMissle.gd.uid b/scripts/Contents/Weapons/MagicMissle.gd.uid new file mode 100644 index 0000000..397acef --- /dev/null +++ b/scripts/Contents/Weapons/MagicMissle.gd.uid @@ -0,0 +1 @@ +uid://clec7nrtesipu diff --git a/scripts/Statemachine/BulletBase.gd b/scripts/Statemachine/BulletBase.gd index ae63458..3c94303 100644 --- a/scripts/Statemachine/BulletBase.gd +++ b/scripts/Statemachine/BulletBase.gd @@ -38,6 +38,7 @@ var initialDamage: float = 0 var speedScale: float = 1 var isFirstFrame: bool = true var cycleStateAngle: float = 0 +var lastDelta: float = 0 func _ready(): initialSpeed = speed @@ -83,7 +84,8 @@ func _process(_delta: float) -> void: if lifeDistance > 0: if position.distance_to(spawnInWhere) >= lifeDistance: tryDestroy() -func _physics_process(_delta: float) -> void: +func _physics_process(delta: float) -> void: + lastDelta = delta if destroying: return if is_instance_valid(launcher) and (launcher.isPlayer() or is_instance_valid(launcher.currentFocusedBoss)): launcher.position -= Vector2.from_angle(rotation) * recoil diff --git a/scripts/Structs/Weapon.gd b/scripts/Structs/Weapon.gd index 04d6d25..e35f3dd 100644 --- a/scripts/Structs/Weapon.gd +++ b/scripts/Structs/Weapon.gd @@ -6,7 +6,7 @@ enum EmitType { HOLD_SHOOT, CLICK_SHOOT, CHARGE, - HOLD_ONCE + HOLD_LOOP } @export var avatarTexture: Texture2D = null @@ -49,6 +49,7 @@ var cooldownTimer: CooldownTimer = null var originalStore: Dictionary = {} var chargedTime: float = 0 var attackSpeed: float = 1 +var looping: bool = false func _ready(): cooldownTimer = CooldownTimer.new() @@ -188,19 +189,41 @@ func canAttackBy(entity: EntityBase): cooldownTimer.speedScale = entity.fields.get(FieldStore.Entity.ATTACK_SPEED) * attackSpeed return cooldownTimer.isCooldowned() and entity.isEnergyEnough(needEnergy) and checkAttack(entity) func tryAttack(entity: EntityBase): - if canAttackBy(entity): - var result = await attack(entity) - if result: - cooldownTimer.start() - entity.useEnergy(needEnergy) - return result + if looping: + if checkAttack(entity): + return await attack(entity) + else: + exitLoop(entity) + else: + if canAttackBy(entity): + if emitType == EmitType.HOLD_LOOP: + var result = await loopStart(entity) + if result: + looping = true + cooldownTimer.start() + entity.useEnergy(needEnergy) + return result + else: + var result = await attack(entity) + if result: + cooldownTimer.start() + entity.useEnergy(needEnergy) + return result func charged(base: float, percent: float): return base * sqrt(1 + chargedTime / 15 * percent) +func exitLoop(entity: EntityBase): + if !looping: return + looping = false + loopExit(entity) # 抽象 func update(_to: int, origin: Dictionary, _entity: EntityBase): return origin +func loopStart(_entity: EntityBase): + pass func checkAttack(_entity: EntityBase) -> bool: return true func attack(_entity: EntityBase): pass +func loopExit(_entity: EntityBase): + pass