Compare commits
2 Commits
main
...
claude/mak
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5d046c91a | ||
|
|
c2804fe1a6 |
524
assets/Effect/ymir work/effect/background/moonlight_eff_bat.mse
Normal file
524
assets/Effect/ymir work/effect/background/moonlight_eff_bat.mse
Normal file
@@ -0,0 +1,524 @@
|
||||
BoundingSphereRadius 0.000000
|
||||
BoundingSpherePosition 0.000000 0.000000 0.000000
|
||||
|
||||
Group Particle
|
||||
{
|
||||
StartTime 0.176000
|
||||
List TimeEventPosition
|
||||
{
|
||||
0.000000 "MOVING_TYPE_DIRECT" 0.000000 0.000000 0.000000
|
||||
}
|
||||
|
||||
StaticRotation 0.000000 0.000000 0.000000
|
||||
Group EmitterProperty
|
||||
{
|
||||
MaxEmissionCount 1
|
||||
|
||||
CycleLength 10.000000
|
||||
CycleLoopEnable 1
|
||||
LoopCount 3
|
||||
|
||||
EmitterShape 0
|
||||
EmitterAdvancedType 0
|
||||
EmitterEmitFromEdgeFlag 0
|
||||
EmittingDirection 0.080000 0.000000 0.000000
|
||||
|
||||
List TimeEventEmittingSize
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingAngularVelocity
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionX
|
||||
{
|
||||
0.000000 5.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionY
|
||||
{
|
||||
0.000000 -50.000000
|
||||
0.100000 -20.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionZ
|
||||
{
|
||||
0.000000 10.000000
|
||||
0.050000 100.000000
|
||||
0.100000 1000.000000
|
||||
}
|
||||
List TimeEventEmittingVelocity
|
||||
{
|
||||
0.000000 15.000000
|
||||
}
|
||||
List TimeEventEmissionCountPerSecond
|
||||
{
|
||||
0.000000 1000.000000
|
||||
}
|
||||
List TimeEventLifeTime
|
||||
{
|
||||
0.000000 10.000000
|
||||
}
|
||||
List TimeEventSizeX
|
||||
{
|
||||
0.000000 60.000000
|
||||
}
|
||||
List TimeEventSizeY
|
||||
{
|
||||
0.000000 36.000000
|
||||
}
|
||||
}
|
||||
|
||||
Group ParticleProperty
|
||||
{
|
||||
SrcBlendType 5
|
||||
DestBlendType 6
|
||||
ColorOperationType 4
|
||||
BillboardType 1
|
||||
RotationType 0
|
||||
RotationSpeed 0.000000
|
||||
RotationRandomStartingBegin 0
|
||||
RotationRandomStartingEnd 0
|
||||
|
||||
AttachEnable 1
|
||||
StretchEnable 0
|
||||
|
||||
TexAniType 1
|
||||
TexAniDelay 0.040000
|
||||
TexAniRandomStartFrameEnable 0
|
||||
EnableFrustum 0
|
||||
|
||||
List TimeEventGravity
|
||||
{
|
||||
}
|
||||
List TimeEventAirResistance
|
||||
{
|
||||
}
|
||||
List TimeEventScaleX
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventScaleY
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorRed
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorGreen
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorBlue
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventAlpha
|
||||
{
|
||||
0.000000 1.000000
|
||||
0.737143 1.000000
|
||||
1.000000 0.000000
|
||||
}
|
||||
List TimeEventRotation
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TextureFiles
|
||||
{
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_01.dds"
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_02.dds"
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_03.dds"
|
||||
}
|
||||
}
|
||||
}
|
||||
Group Particle
|
||||
{
|
||||
StartTime 0.072000
|
||||
List TimeEventPosition
|
||||
{
|
||||
0.000000 "MOVING_TYPE_DIRECT" 0.000000 0.000000 0.000000
|
||||
}
|
||||
|
||||
StaticRotation 0.000000 0.000000 0.000000
|
||||
Group EmitterProperty
|
||||
{
|
||||
MaxEmissionCount 1
|
||||
|
||||
CycleLength 10.000000
|
||||
CycleLoopEnable 1
|
||||
LoopCount 3
|
||||
|
||||
EmitterShape 0
|
||||
EmitterAdvancedType 0
|
||||
EmitterEmitFromEdgeFlag 0
|
||||
EmittingDirection 0.080000 0.000000 0.000000
|
||||
|
||||
List TimeEventEmittingSize
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingAngularVelocity
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionX
|
||||
{
|
||||
0.000000 15.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionY
|
||||
{
|
||||
0.000000 -50.000000
|
||||
0.100000 -20.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionZ
|
||||
{
|
||||
0.000000 10.000000
|
||||
0.050000 50.000000
|
||||
0.100000 1000.000000
|
||||
}
|
||||
List TimeEventEmittingVelocity
|
||||
{
|
||||
0.000000 15.000000
|
||||
}
|
||||
List TimeEventEmissionCountPerSecond
|
||||
{
|
||||
0.000000 1000.000000
|
||||
}
|
||||
List TimeEventLifeTime
|
||||
{
|
||||
0.000000 10.000000
|
||||
}
|
||||
List TimeEventSizeX
|
||||
{
|
||||
0.000000 72.000000
|
||||
}
|
||||
List TimeEventSizeY
|
||||
{
|
||||
0.000000 48.000000
|
||||
}
|
||||
}
|
||||
|
||||
Group ParticleProperty
|
||||
{
|
||||
SrcBlendType 5
|
||||
DestBlendType 6
|
||||
ColorOperationType 4
|
||||
BillboardType 1
|
||||
RotationType 0
|
||||
RotationSpeed 0.000000
|
||||
RotationRandomStartingBegin 0
|
||||
RotationRandomStartingEnd 0
|
||||
|
||||
AttachEnable 1
|
||||
StretchEnable 0
|
||||
|
||||
TexAniType 1
|
||||
TexAniDelay 0.040000
|
||||
TexAniRandomStartFrameEnable 0
|
||||
EnableFrustum 0
|
||||
|
||||
List TimeEventGravity
|
||||
{
|
||||
}
|
||||
List TimeEventAirResistance
|
||||
{
|
||||
}
|
||||
List TimeEventScaleX
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventScaleY
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorRed
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorGreen
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorBlue
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventAlpha
|
||||
{
|
||||
0.000000 1.000000
|
||||
0.737143 1.000000
|
||||
1.000000 0.000000
|
||||
}
|
||||
List TimeEventRotation
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TextureFiles
|
||||
{
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_01.dds"
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_02.dds"
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_03.dds"
|
||||
}
|
||||
}
|
||||
}
|
||||
Group Particle
|
||||
{
|
||||
StartTime 0.000000
|
||||
List TimeEventPosition
|
||||
{
|
||||
0.000000 "MOVING_TYPE_DIRECT" 0.000000 0.000000 0.000000
|
||||
}
|
||||
|
||||
StaticRotation 0.000000 0.000000 0.000000
|
||||
Group EmitterProperty
|
||||
{
|
||||
MaxEmissionCount 1
|
||||
|
||||
CycleLength 10.000000
|
||||
CycleLoopEnable 1
|
||||
LoopCount 3
|
||||
|
||||
EmitterShape 0
|
||||
EmitterAdvancedType 0
|
||||
EmitterEmitFromEdgeFlag 0
|
||||
EmittingDirection 0.080000 0.000000 0.000000
|
||||
|
||||
List TimeEventEmittingSize
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingAngularVelocity
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionX
|
||||
{
|
||||
0.000000 50.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionY
|
||||
{
|
||||
0.000000 -50.000000
|
||||
0.100000 -20.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionZ
|
||||
{
|
||||
0.000000 10.000000
|
||||
0.050000 100.000000
|
||||
0.100000 1000.000000
|
||||
}
|
||||
List TimeEventEmittingVelocity
|
||||
{
|
||||
0.000000 5.000000
|
||||
0.083429 15.000000
|
||||
}
|
||||
List TimeEventEmissionCountPerSecond
|
||||
{
|
||||
0.000000 1000.000000
|
||||
}
|
||||
List TimeEventLifeTime
|
||||
{
|
||||
0.000000 10.000000
|
||||
}
|
||||
List TimeEventSizeX
|
||||
{
|
||||
0.000000 60.000000
|
||||
}
|
||||
List TimeEventSizeY
|
||||
{
|
||||
0.000000 36.000000
|
||||
}
|
||||
}
|
||||
|
||||
Group ParticleProperty
|
||||
{
|
||||
SrcBlendType 5
|
||||
DestBlendType 6
|
||||
ColorOperationType 4
|
||||
BillboardType 1
|
||||
RotationType 0
|
||||
RotationSpeed 0.000000
|
||||
RotationRandomStartingBegin 0
|
||||
RotationRandomStartingEnd 0
|
||||
|
||||
AttachEnable 1
|
||||
StretchEnable 0
|
||||
|
||||
TexAniType 1
|
||||
TexAniDelay 0.040000
|
||||
TexAniRandomStartFrameEnable 0
|
||||
EnableFrustum 0
|
||||
|
||||
List TimeEventGravity
|
||||
{
|
||||
}
|
||||
List TimeEventAirResistance
|
||||
{
|
||||
}
|
||||
List TimeEventScaleX
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventScaleY
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorRed
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorGreen
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorBlue
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventAlpha
|
||||
{
|
||||
0.000000 1.000000
|
||||
0.737143 1.000000
|
||||
1.000000 0.000000
|
||||
}
|
||||
List TimeEventRotation
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TextureFiles
|
||||
{
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_01.dds"
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_02.dds"
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_03.dds"
|
||||
}
|
||||
}
|
||||
}
|
||||
Group Particle
|
||||
{
|
||||
StartTime 0.000000
|
||||
List TimeEventPosition
|
||||
{
|
||||
0.000000 "MOVING_TYPE_DIRECT" 0.000000 0.000000 0.000000
|
||||
0.216000 "MOVING_TYPE_DIRECT" 0.000000 -20.000000 20.000000
|
||||
}
|
||||
|
||||
StaticRotation 0.000000 0.000000 0.000000
|
||||
Group EmitterProperty
|
||||
{
|
||||
MaxEmissionCount 30
|
||||
|
||||
CycleLength 10.000000
|
||||
CycleLoopEnable 1
|
||||
LoopCount 3
|
||||
|
||||
EmitterShape 3
|
||||
EmitterAdvancedType 1
|
||||
EmittingRadius 80.000000
|
||||
EmitterEmitFromEdgeFlag 0
|
||||
EmittingDirection 0.010000 0.010000 0.010000
|
||||
|
||||
List TimeEventEmittingSize
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingAngularVelocity
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionX
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionY
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionZ
|
||||
{
|
||||
0.000000 20.000000
|
||||
}
|
||||
List TimeEventEmittingVelocity
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventEmissionCountPerSecond
|
||||
{
|
||||
0.000000 1000.000000
|
||||
}
|
||||
List TimeEventLifeTime
|
||||
{
|
||||
0.000000 10.000000
|
||||
}
|
||||
List TimeEventSizeX
|
||||
{
|
||||
0.000000 128.000000
|
||||
}
|
||||
List TimeEventSizeY
|
||||
{
|
||||
0.000000 128.000000
|
||||
}
|
||||
}
|
||||
|
||||
Group ParticleProperty
|
||||
{
|
||||
SrcBlendType 5
|
||||
DestBlendType 6
|
||||
ColorOperationType 4
|
||||
BillboardType 1
|
||||
RotationType 4
|
||||
RotationSpeed 56.000000
|
||||
RotationRandomStartingBegin 360
|
||||
RotationRandomStartingEnd 0
|
||||
|
||||
AttachEnable 0
|
||||
StretchEnable 0
|
||||
|
||||
TexAniType 0
|
||||
TexAniDelay 0.040000
|
||||
TexAniRandomStartFrameEnable 0
|
||||
EnableFrustum 0
|
||||
|
||||
List TimeEventGravity
|
||||
{
|
||||
}
|
||||
List TimeEventAirResistance
|
||||
{
|
||||
0.000000 0.000000
|
||||
0.034286 0.100000
|
||||
}
|
||||
List TimeEventScaleX
|
||||
{
|
||||
0.000000 0.500000
|
||||
1.000000 1.000000
|
||||
}
|
||||
List TimeEventScaleY
|
||||
{
|
||||
0.000000 0.500000
|
||||
1.000000 1.000000
|
||||
}
|
||||
List TimeEventColorRed
|
||||
{
|
||||
0.000000 0.819608
|
||||
}
|
||||
List TimeEventColorGreen
|
||||
{
|
||||
0.000000 0.780392
|
||||
}
|
||||
List TimeEventColorBlue
|
||||
{
|
||||
0.000000 0.682353
|
||||
}
|
||||
List TimeEventAlpha
|
||||
{
|
||||
0.000000 1.000000
|
||||
0.112821 0.000000
|
||||
}
|
||||
List TimeEventRotation
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TextureFiles
|
||||
{
|
||||
"D:\Ymir Work\effect\monster2\smoke_dirt1.dds"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,654 @@
|
||||
BoundingSphereRadius 0.000000
|
||||
BoundingSpherePosition 0.000000 0.000000 0.000000
|
||||
|
||||
Group Particle
|
||||
{
|
||||
StartTime 0.176000
|
||||
List TimeEventPosition
|
||||
{
|
||||
0.000000 "MOVING_TYPE_DIRECT" 0.000000 0.000000 0.000000
|
||||
}
|
||||
|
||||
StaticRotation 0.000000 0.000000 0.000000
|
||||
Group EmitterProperty
|
||||
{
|
||||
MaxEmissionCount 1
|
||||
|
||||
CycleLength 20.000000
|
||||
CycleLoopEnable 1
|
||||
LoopCount 2
|
||||
|
||||
EmitterShape 0
|
||||
EmitterAdvancedType 0
|
||||
EmitterEmitFromEdgeFlag 0
|
||||
EmittingDirection 0.080000 0.000000 0.000000
|
||||
|
||||
List TimeEventEmittingSize
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingAngularVelocity
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionX
|
||||
{
|
||||
0.000000 5.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionY
|
||||
{
|
||||
0.000000 50.000000
|
||||
0.100000 20.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionZ
|
||||
{
|
||||
0.000000 10.000000
|
||||
0.050000 100.000000
|
||||
0.100000 1000.000000
|
||||
}
|
||||
List TimeEventEmittingVelocity
|
||||
{
|
||||
0.000000 15.000000
|
||||
}
|
||||
List TimeEventEmissionCountPerSecond
|
||||
{
|
||||
0.000000 1000.000000
|
||||
}
|
||||
List TimeEventLifeTime
|
||||
{
|
||||
0.000000 20.000000
|
||||
}
|
||||
List TimeEventSizeX
|
||||
{
|
||||
0.000000 60.000000
|
||||
}
|
||||
List TimeEventSizeY
|
||||
{
|
||||
0.000000 36.000000
|
||||
}
|
||||
}
|
||||
|
||||
Group ParticleProperty
|
||||
{
|
||||
SrcBlendType 5
|
||||
DestBlendType 6
|
||||
ColorOperationType 4
|
||||
BillboardType 1
|
||||
RotationType 0
|
||||
RotationSpeed 0.000000
|
||||
RotationRandomStartingBegin 0
|
||||
RotationRandomStartingEnd 0
|
||||
|
||||
AttachEnable 1
|
||||
StretchEnable 0
|
||||
|
||||
TexAniType 1
|
||||
TexAniDelay 0.040000
|
||||
TexAniRandomStartFrameEnable 0
|
||||
EnableFrustum 0
|
||||
|
||||
List TimeEventGravity
|
||||
{
|
||||
}
|
||||
List TimeEventAirResistance
|
||||
{
|
||||
}
|
||||
List TimeEventScaleX
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventScaleY
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorRed
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorGreen
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorBlue
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventAlpha
|
||||
{
|
||||
0.000000 1.000000
|
||||
0.376923 1.000000
|
||||
0.500000 0.000000
|
||||
}
|
||||
List TimeEventRotation
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TextureFiles
|
||||
{
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_01.dds"
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_02.dds"
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_03.dds"
|
||||
}
|
||||
}
|
||||
}
|
||||
Group Particle
|
||||
{
|
||||
StartTime 0.072000
|
||||
List TimeEventPosition
|
||||
{
|
||||
0.000000 "MOVING_TYPE_DIRECT" 0.000000 0.000000 0.000000
|
||||
}
|
||||
|
||||
StaticRotation 0.000000 0.000000 0.000000
|
||||
Group EmitterProperty
|
||||
{
|
||||
MaxEmissionCount 1
|
||||
|
||||
CycleLength 20.000000
|
||||
CycleLoopEnable 1
|
||||
LoopCount 2
|
||||
|
||||
EmitterShape 0
|
||||
EmitterAdvancedType 0
|
||||
EmitterEmitFromEdgeFlag 0
|
||||
EmittingDirection 0.080000 0.000000 0.000000
|
||||
|
||||
List TimeEventEmittingSize
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingAngularVelocity
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionX
|
||||
{
|
||||
0.000000 15.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionY
|
||||
{
|
||||
0.000000 50.000000
|
||||
0.100000 20.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionZ
|
||||
{
|
||||
0.000000 10.000000
|
||||
0.050000 50.000000
|
||||
0.100000 1000.000000
|
||||
}
|
||||
List TimeEventEmittingVelocity
|
||||
{
|
||||
0.000000 15.000000
|
||||
}
|
||||
List TimeEventEmissionCountPerSecond
|
||||
{
|
||||
0.000000 1000.000000
|
||||
}
|
||||
List TimeEventLifeTime
|
||||
{
|
||||
0.000000 20.000000
|
||||
}
|
||||
List TimeEventSizeX
|
||||
{
|
||||
0.000000 72.000000
|
||||
}
|
||||
List TimeEventSizeY
|
||||
{
|
||||
0.000000 48.000000
|
||||
}
|
||||
}
|
||||
|
||||
Group ParticleProperty
|
||||
{
|
||||
SrcBlendType 5
|
||||
DestBlendType 6
|
||||
ColorOperationType 4
|
||||
BillboardType 1
|
||||
RotationType 0
|
||||
RotationSpeed 0.000000
|
||||
RotationRandomStartingBegin 0
|
||||
RotationRandomStartingEnd 0
|
||||
|
||||
AttachEnable 1
|
||||
StretchEnable 0
|
||||
|
||||
TexAniType 1
|
||||
TexAniDelay 0.040000
|
||||
TexAniRandomStartFrameEnable 0
|
||||
EnableFrustum 0
|
||||
|
||||
List TimeEventGravity
|
||||
{
|
||||
}
|
||||
List TimeEventAirResistance
|
||||
{
|
||||
}
|
||||
List TimeEventScaleX
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventScaleY
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorRed
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorGreen
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorBlue
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventAlpha
|
||||
{
|
||||
0.000000 1.000000
|
||||
0.387179 1.000000
|
||||
0.517949 0.000000
|
||||
}
|
||||
List TimeEventRotation
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TextureFiles
|
||||
{
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_01.dds"
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_02.dds"
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_03.dds"
|
||||
}
|
||||
}
|
||||
}
|
||||
Group Particle
|
||||
{
|
||||
StartTime 0.072000
|
||||
List TimeEventPosition
|
||||
{
|
||||
0.000000 "MOVING_TYPE_DIRECT" 0.000000 0.000000 0.000000
|
||||
}
|
||||
|
||||
StaticRotation 0.000000 0.000000 0.000000
|
||||
Group EmitterProperty
|
||||
{
|
||||
MaxEmissionCount 1
|
||||
|
||||
CycleLength 20.000000
|
||||
CycleLoopEnable 1
|
||||
LoopCount 2
|
||||
|
||||
EmitterShape 0
|
||||
EmitterAdvancedType 0
|
||||
EmitterEmitFromEdgeFlag 0
|
||||
EmittingDirection 0.080000 0.000000 0.000000
|
||||
|
||||
List TimeEventEmittingSize
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingAngularVelocity
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionX
|
||||
{
|
||||
0.000000 15.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionY
|
||||
{
|
||||
0.000000 50.000000
|
||||
0.100000 20.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionZ
|
||||
{
|
||||
0.000000 10.000000
|
||||
0.050000 50.000000
|
||||
0.100000 1000.000000
|
||||
}
|
||||
List TimeEventEmittingVelocity
|
||||
{
|
||||
0.000000 15.000000
|
||||
}
|
||||
List TimeEventEmissionCountPerSecond
|
||||
{
|
||||
0.000000 1000.000000
|
||||
}
|
||||
List TimeEventLifeTime
|
||||
{
|
||||
0.000000 20.000000
|
||||
}
|
||||
List TimeEventSizeX
|
||||
{
|
||||
0.000000 72.000000
|
||||
}
|
||||
List TimeEventSizeY
|
||||
{
|
||||
0.000000 48.000000
|
||||
}
|
||||
}
|
||||
|
||||
Group ParticleProperty
|
||||
{
|
||||
SrcBlendType 5
|
||||
DestBlendType 6
|
||||
ColorOperationType 4
|
||||
BillboardType 1
|
||||
RotationType 0
|
||||
RotationSpeed 0.000000
|
||||
RotationRandomStartingBegin 0
|
||||
RotationRandomStartingEnd 0
|
||||
|
||||
AttachEnable 1
|
||||
StretchEnable 0
|
||||
|
||||
TexAniType 1
|
||||
TexAniDelay 0.040000
|
||||
TexAniRandomStartFrameEnable 0
|
||||
EnableFrustum 0
|
||||
|
||||
List TimeEventGravity
|
||||
{
|
||||
}
|
||||
List TimeEventAirResistance
|
||||
{
|
||||
}
|
||||
List TimeEventScaleX
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventScaleY
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorRed
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorGreen
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorBlue
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventAlpha
|
||||
{
|
||||
0.000000 1.000000
|
||||
0.405128 1.000000
|
||||
0.505128 0.000000
|
||||
}
|
||||
List TimeEventRotation
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TextureFiles
|
||||
{
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_01.dds"
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_02.dds"
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_03.dds"
|
||||
}
|
||||
}
|
||||
}
|
||||
Group Particle
|
||||
{
|
||||
StartTime 0.000000
|
||||
List TimeEventPosition
|
||||
{
|
||||
0.000000 "MOVING_TYPE_DIRECT" 0.000000 0.000000 0.000000
|
||||
}
|
||||
|
||||
StaticRotation 0.000000 0.000000 0.000000
|
||||
Group EmitterProperty
|
||||
{
|
||||
MaxEmissionCount 1
|
||||
|
||||
CycleLength 20.000000
|
||||
CycleLoopEnable 1
|
||||
LoopCount 2
|
||||
|
||||
EmitterShape 0
|
||||
EmitterAdvancedType 0
|
||||
EmitterEmitFromEdgeFlag 0
|
||||
EmittingDirection 0.100000 0.000000 0.050000
|
||||
|
||||
List TimeEventEmittingSize
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingAngularVelocity
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionX
|
||||
{
|
||||
0.000000 50.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionY
|
||||
{
|
||||
0.000000 50.000000
|
||||
0.100000 20.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionZ
|
||||
{
|
||||
0.000000 10.000000
|
||||
0.050000 100.000000
|
||||
0.100000 1000.000000
|
||||
}
|
||||
List TimeEventEmittingVelocity
|
||||
{
|
||||
0.000000 5.000000
|
||||
0.083429 15.000000
|
||||
}
|
||||
List TimeEventEmissionCountPerSecond
|
||||
{
|
||||
0.000000 1000.000000
|
||||
}
|
||||
List TimeEventLifeTime
|
||||
{
|
||||
0.000000 20.000000
|
||||
}
|
||||
List TimeEventSizeX
|
||||
{
|
||||
0.000000 60.000000
|
||||
}
|
||||
List TimeEventSizeY
|
||||
{
|
||||
0.000000 36.000000
|
||||
}
|
||||
}
|
||||
|
||||
Group ParticleProperty
|
||||
{
|
||||
SrcBlendType 5
|
||||
DestBlendType 6
|
||||
ColorOperationType 4
|
||||
BillboardType 1
|
||||
RotationType 0
|
||||
RotationSpeed 0.000000
|
||||
RotationRandomStartingBegin 0
|
||||
RotationRandomStartingEnd 0
|
||||
|
||||
AttachEnable 1
|
||||
StretchEnable 0
|
||||
|
||||
TexAniType 1
|
||||
TexAniDelay 0.040000
|
||||
TexAniRandomStartFrameEnable 0
|
||||
EnableFrustum 0
|
||||
|
||||
List TimeEventGravity
|
||||
{
|
||||
}
|
||||
List TimeEventAirResistance
|
||||
{
|
||||
}
|
||||
List TimeEventScaleX
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventScaleY
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorRed
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorGreen
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventColorBlue
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventAlpha
|
||||
{
|
||||
0.000000 1.000000
|
||||
0.382051 1.000000
|
||||
0.500000 0.000000
|
||||
}
|
||||
List TimeEventRotation
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TextureFiles
|
||||
{
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_01.dds"
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_02.dds"
|
||||
"D:\Ymir Work\effect\pet\halloween_2022_coffin_bat_03.dds"
|
||||
}
|
||||
}
|
||||
}
|
||||
Group Particle
|
||||
{
|
||||
StartTime 0.000000
|
||||
List TimeEventPosition
|
||||
{
|
||||
0.000000 "MOVING_TYPE_DIRECT" 0.000000 0.000000 0.000000
|
||||
0.216000 "MOVING_TYPE_DIRECT" 0.000000 -20.000000 20.000000
|
||||
}
|
||||
|
||||
StaticRotation 0.000000 0.000000 0.000000
|
||||
Group EmitterProperty
|
||||
{
|
||||
MaxEmissionCount 30
|
||||
|
||||
CycleLength 20.000000
|
||||
CycleLoopEnable 1
|
||||
LoopCount 2
|
||||
|
||||
EmitterShape 3
|
||||
EmitterAdvancedType 1
|
||||
EmittingRadius 80.000000
|
||||
EmitterEmitFromEdgeFlag 0
|
||||
EmittingDirection 0.010000 0.010000 0.010000
|
||||
|
||||
List TimeEventEmittingSize
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingAngularVelocity
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionX
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionY
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TimeEventEmittingDirectionZ
|
||||
{
|
||||
0.000000 20.000000
|
||||
}
|
||||
List TimeEventEmittingVelocity
|
||||
{
|
||||
0.000000 1.000000
|
||||
}
|
||||
List TimeEventEmissionCountPerSecond
|
||||
{
|
||||
0.000000 1000.000000
|
||||
}
|
||||
List TimeEventLifeTime
|
||||
{
|
||||
0.000000 20.000000
|
||||
}
|
||||
List TimeEventSizeX
|
||||
{
|
||||
0.000000 128.000000
|
||||
}
|
||||
List TimeEventSizeY
|
||||
{
|
||||
0.000000 128.000000
|
||||
}
|
||||
}
|
||||
|
||||
Group ParticleProperty
|
||||
{
|
||||
SrcBlendType 5
|
||||
DestBlendType 6
|
||||
ColorOperationType 4
|
||||
BillboardType 1
|
||||
RotationType 4
|
||||
RotationSpeed 56.000000
|
||||
RotationRandomStartingBegin 360
|
||||
RotationRandomStartingEnd 0
|
||||
|
||||
AttachEnable 0
|
||||
StretchEnable 0
|
||||
|
||||
TexAniType 0
|
||||
TexAniDelay 0.040000
|
||||
TexAniRandomStartFrameEnable 0
|
||||
EnableFrustum 0
|
||||
|
||||
List TimeEventGravity
|
||||
{
|
||||
}
|
||||
List TimeEventAirResistance
|
||||
{
|
||||
0.000000 0.000000
|
||||
0.034286 0.100000
|
||||
}
|
||||
List TimeEventScaleX
|
||||
{
|
||||
0.000000 0.500000
|
||||
1.000000 1.000000
|
||||
}
|
||||
List TimeEventScaleY
|
||||
{
|
||||
0.000000 0.500000
|
||||
1.000000 1.000000
|
||||
}
|
||||
List TimeEventColorRed
|
||||
{
|
||||
0.000000 0.819608
|
||||
}
|
||||
List TimeEventColorGreen
|
||||
{
|
||||
0.000000 0.780392
|
||||
}
|
||||
List TimeEventColorBlue
|
||||
{
|
||||
0.000000 0.682353
|
||||
}
|
||||
List TimeEventAlpha
|
||||
{
|
||||
0.000000 1.000000
|
||||
0.050000 0.000000
|
||||
}
|
||||
List TimeEventRotation
|
||||
{
|
||||
0.000000 0.000000
|
||||
}
|
||||
List TextureFiles
|
||||
{
|
||||
"D:\Ymir Work\effect\monster2\smoke_dirt1.dds"
|
||||
}
|
||||
}
|
||||
}
|
||||
35
assets/Effect/ymir work/effect/background/mushrooma_01.mse
Normal file
35
assets/Effect/ymir work/effect/background/mushrooma_01.mse
Normal file
@@ -0,0 +1,35 @@
|
||||
BoundingSphereRadius 400.000000
|
||||
BoundingSpherePosition -180.000000 -60.000000 650.000000
|
||||
|
||||
Group Mesh
|
||||
{
|
||||
StartTime 0.000000
|
||||
List TimeEventPosition
|
||||
{
|
||||
0.000000 "MOVING_TYPE_DIRECT" 0.000000 0.000000 0.000000
|
||||
}
|
||||
|
||||
MeshFileName "mushroomA_01.mde"
|
||||
MeshAnimationLoopEnable 1
|
||||
MeshAnimationLoopCount 0
|
||||
MeshAnimationFrameDelay 0.020000
|
||||
|
||||
MeshElementCount 1
|
||||
Group MeshElement00
|
||||
{
|
||||
BillboardType 0
|
||||
BlendingEnable 1
|
||||
BlendingSrcType 5
|
||||
BlendingDestType 2
|
||||
|
||||
TextureAnimationLoopEnable 1
|
||||
TextureAnimationFrameDelay 0.020000
|
||||
TextureAnimationStartFrame 0
|
||||
|
||||
ColorOperationType 5
|
||||
ColorFactor 0.168627 0.643137 0.360784 1.000000
|
||||
List TimeEventAlpha
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
35
assets/Effect/ymir work/effect/background/mushrooma_03.mse
Normal file
35
assets/Effect/ymir work/effect/background/mushrooma_03.mse
Normal file
@@ -0,0 +1,35 @@
|
||||
BoundingSphereRadius 500.000000
|
||||
BoundingSpherePosition 100.000000 0.000000 550.000000
|
||||
|
||||
Group Mesh
|
||||
{
|
||||
StartTime 0.000000
|
||||
List TimeEventPosition
|
||||
{
|
||||
0.000000 "MOVING_TYPE_DIRECT" 0.000000 0.000000 0.000000
|
||||
}
|
||||
|
||||
MeshFileName "mushroomA_03.mde"
|
||||
MeshAnimationLoopEnable 1
|
||||
MeshAnimationLoopCount 0
|
||||
MeshAnimationFrameDelay 0.020000
|
||||
|
||||
MeshElementCount 1
|
||||
Group MeshElement00
|
||||
{
|
||||
BillboardType 0
|
||||
BlendingEnable 1
|
||||
BlendingSrcType 5
|
||||
BlendingDestType 2
|
||||
|
||||
TextureAnimationLoopEnable 1
|
||||
TextureAnimationFrameDelay 0.020000
|
||||
TextureAnimationStartFrame 0
|
||||
|
||||
ColorOperationType 5
|
||||
ColorFactor 0.184314 0.643137 0.462745 1.000000
|
||||
List TimeEventAlpha
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
35
assets/Effect/ymir work/effect/background/mushrooma_04.mse
Normal file
35
assets/Effect/ymir work/effect/background/mushrooma_04.mse
Normal file
@@ -0,0 +1,35 @@
|
||||
BoundingSphereRadius 330.000000
|
||||
BoundingSpherePosition -160.000000 0.000000 370.000000
|
||||
|
||||
Group Mesh
|
||||
{
|
||||
StartTime 0.000000
|
||||
List TimeEventPosition
|
||||
{
|
||||
0.000000 "MOVING_TYPE_DIRECT" 0.000000 0.000000 0.000000
|
||||
}
|
||||
|
||||
MeshFileName "mushroomA_04.mde"
|
||||
MeshAnimationLoopEnable 1
|
||||
MeshAnimationLoopCount 0
|
||||
MeshAnimationFrameDelay 0.020000
|
||||
|
||||
MeshElementCount 1
|
||||
Group MeshElement00
|
||||
{
|
||||
BillboardType 0
|
||||
BlendingEnable 1
|
||||
BlendingSrcType 5
|
||||
BlendingDestType 2
|
||||
|
||||
TextureAnimationLoopEnable 1
|
||||
TextureAnimationFrameDelay 0.020000
|
||||
TextureAnimationStartFrame 0
|
||||
|
||||
ColorOperationType 5
|
||||
ColorFactor 0.200000 0.521569 0.227451 1.000000
|
||||
List TimeEventAlpha
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
BoundingSphereRadius 2500.000000
|
||||
BoundingSpherePosition 0.000000 0.000000 1800.000000
|
||||
|
||||
Group Mesh
|
||||
{
|
||||
StartTime 0.000000
|
||||
List TimeEventPosition
|
||||
{
|
||||
0.000000 "MOVING_TYPE_DIRECT" 0.000000 0.000000 0.000000
|
||||
}
|
||||
|
||||
MeshFileName "turtle_statue_tree_roof_light01.mde"
|
||||
MeshAnimationLoopEnable 1
|
||||
MeshAnimationLoopCount 0
|
||||
MeshAnimationFrameDelay 0.020000
|
||||
|
||||
MeshElementCount 1
|
||||
Group MeshElement00
|
||||
{
|
||||
BillboardType 0
|
||||
BlendingEnable 1
|
||||
BlendingSrcType 5
|
||||
BlendingDestType 2
|
||||
|
||||
TextureAnimationLoopEnable 1
|
||||
TextureAnimationFrameDelay 0.020000
|
||||
TextureAnimationStartFrame 0
|
||||
|
||||
ColorOperationType 5
|
||||
ColorFactor 0.772549 0.733333 0.188235 1.000000
|
||||
List TimeEventAlpha
|
||||
{
|
||||
0.046667 0.577320
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,4 +1,5 @@
|
||||
ScriptType MotionData
|
||||
|
||||
MotionFileName "D:\Ymir Work\monster\orc_lord\30_1.GR2"
|
||||
MotionFileName "D:\Ymir Work\monster\orc_lord\32_1.GR2"
|
||||
MotionDuration 0.833333
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -55,157 +55,6 @@ from _weakref import proxy
|
||||
SCREENSHOT_CWDSAVE = False
|
||||
SCREENSHOT_DIR = None
|
||||
|
||||
|
||||
def _WriteHeadlessMapTrace(message):
|
||||
if os.environ.get("M2_HEADLESS_SCENARIO", "").strip().lower() != "map_load":
|
||||
return
|
||||
|
||||
try:
|
||||
open("log/headless_map_load_trace.txt", "a").write("%s\n" % message)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def _GetHeadlessScenario():
|
||||
return os.environ.get("M2_HEADLESS_SCENARIO", "").strip().lower()
|
||||
|
||||
|
||||
def _WriteHeadlessTrace(message):
|
||||
scenario = _GetHeadlessScenario()
|
||||
if scenario == "map_load":
|
||||
tracePath = "log/headless_map_load_trace.txt"
|
||||
elif scenario == "gm_teleport":
|
||||
tracePath = "log/headless_gm_teleport_trace.txt"
|
||||
else:
|
||||
return
|
||||
|
||||
try:
|
||||
open(tracePath, "a").write("%s\n" % message)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def _GetHeadlessFloat(name, default):
|
||||
try:
|
||||
return float(os.environ.get(name, str(default)))
|
||||
except (TypeError, ValueError):
|
||||
return default
|
||||
|
||||
|
||||
def _GetHeadlessWarpSteps():
|
||||
rawValue = os.environ.get("M2_HEADLESS_WARP_STEPS", "").strip()
|
||||
steps = []
|
||||
|
||||
if not rawValue:
|
||||
return steps
|
||||
|
||||
for rawStep in rawValue.split("|"):
|
||||
rawStep = rawStep.strip()
|
||||
if not rawStep:
|
||||
continue
|
||||
|
||||
parts = [part.strip() for part in rawStep.split(",")]
|
||||
if len(parts) != 3:
|
||||
_WriteHeadlessTrace("Invalid warp step=%s" % rawStep)
|
||||
continue
|
||||
|
||||
mapName = parts[0]
|
||||
|
||||
try:
|
||||
globalX = int(parts[1])
|
||||
globalY = int(parts[2])
|
||||
except:
|
||||
_WriteHeadlessTrace("Invalid warp coords step=%s" % rawStep)
|
||||
continue
|
||||
|
||||
steps.append({
|
||||
"map_name": mapName,
|
||||
"global_x": globalX,
|
||||
"global_y": globalY,
|
||||
})
|
||||
|
||||
return steps
|
||||
|
||||
|
||||
HEADLESS_GM_STATE = {
|
||||
"initialized": False,
|
||||
"steps": [],
|
||||
"index": 0,
|
||||
"phase": "idle",
|
||||
"command_at": 0.0,
|
||||
"deadline": 0.0,
|
||||
"quit_requested": False,
|
||||
}
|
||||
|
||||
|
||||
def _HeadlessGMEnabled():
|
||||
return _GetHeadlessScenario() == "gm_teleport"
|
||||
|
||||
|
||||
def _HeadlessGMCommandDelay():
|
||||
return _GetHeadlessFloat("M2_HEADLESS_COMMAND_DELAY", 5.0)
|
||||
|
||||
|
||||
def _HeadlessGMWarpTimeout():
|
||||
return _GetHeadlessFloat("M2_HEADLESS_WARP_TIMEOUT", 20.0)
|
||||
|
||||
|
||||
def _HeadlessGMSettleDelay():
|
||||
return _GetHeadlessFloat("M2_HEADLESS_SETTLE_DELAY", 2.0)
|
||||
|
||||
|
||||
def _HeadlessGMRequestQuit(message):
|
||||
global HEADLESS_GM_STATE
|
||||
|
||||
if message:
|
||||
_WriteHeadlessTrace(message)
|
||||
|
||||
if HEADLESS_GM_STATE.get("quit_requested"):
|
||||
return
|
||||
|
||||
HEADLESS_GM_STATE["quit_requested"] = True
|
||||
app.Exit()
|
||||
|
||||
|
||||
class _HeadlessDummy(object):
|
||||
def __call__(self, *args, **kwargs):
|
||||
return None
|
||||
|
||||
def __getattr__(self, name):
|
||||
return self
|
||||
|
||||
def __nonzero__(self):
|
||||
return False
|
||||
|
||||
|
||||
_HEADLESS_DUMMY = _HeadlessDummy()
|
||||
|
||||
|
||||
class _HeadlessInterface(object):
|
||||
def MakeInterface(self):
|
||||
return None
|
||||
|
||||
def ShowDefaultWindows(self):
|
||||
return None
|
||||
|
||||
def HideAllWindows(self):
|
||||
return None
|
||||
|
||||
def Close(self):
|
||||
return None
|
||||
|
||||
def BUILD_OnUpdate(self):
|
||||
return None
|
||||
|
||||
def OpenWhisperDialog(self, *args):
|
||||
return None
|
||||
|
||||
def SetMapName(self, *args):
|
||||
return None
|
||||
|
||||
def __getattr__(self, name):
|
||||
return _HEADLESS_DUMMY
|
||||
|
||||
cameraDistance = 1550.0
|
||||
cameraPitch = 27.0
|
||||
cameraRotation = 0.0
|
||||
@@ -215,7 +64,6 @@ testAlignment = 0
|
||||
|
||||
class GameWindow(ui.ScriptWindow):
|
||||
def __init__(self, stream):
|
||||
_WriteHeadlessTrace("GameWindow.__init__ begin")
|
||||
ui.ScriptWindow.__init__(self, "GAME")
|
||||
self.SetWindowName("game")
|
||||
net.SetPhaseWindow(net.PHASE_WINDOW_GAME, self)
|
||||
@@ -224,7 +72,6 @@ class GameWindow(ui.ScriptWindow):
|
||||
self.quickSlotPageIndex = 0
|
||||
self.lastPKModeSendedTime = 0
|
||||
self.pressNumber = None
|
||||
self.headlessGmEnabled = _HeadlessGMEnabled()
|
||||
|
||||
self.guildWarQuestionDialog = None
|
||||
self.interface = None
|
||||
@@ -235,16 +82,9 @@ class GameWindow(ui.ScriptWindow):
|
||||
self.playerGauge = None
|
||||
|
||||
self.stream = stream
|
||||
if self.headlessGmEnabled:
|
||||
self.interface = _HeadlessInterface()
|
||||
_WriteHeadlessTrace("GameWindow.__init__ interface_headless")
|
||||
else:
|
||||
self.interface = interfaceModule.Interface()
|
||||
_WriteHeadlessTrace("GameWindow.__init__ interface")
|
||||
self.interface.MakeInterface()
|
||||
_WriteHeadlessTrace("GameWindow.__init__ interface_made")
|
||||
self.interface.ShowDefaultWindows()
|
||||
_WriteHeadlessTrace("GameWindow.__init__ default_windows")
|
||||
|
||||
self.curtain = uiPhaseCurtain.PhaseCurtain()
|
||||
self.curtain.speed = 0.03
|
||||
@@ -272,7 +112,6 @@ class GameWindow(ui.ScriptWindow):
|
||||
|
||||
self.__ServerCommand_Build()
|
||||
self.__ProcessPreservedServerCommand()
|
||||
_WriteHeadlessTrace("GameWindow.__init__ done")
|
||||
|
||||
def __del__(self):
|
||||
player.SetGameWindow(0)
|
||||
@@ -294,10 +133,6 @@ class GameWindow(ui.ScriptWindow):
|
||||
self.enableXMasBoom = False
|
||||
self.startTimeXMasBoom = 0.0
|
||||
self.indexXMasBoom = 0
|
||||
currentMap = background.GetCurrentMapName()
|
||||
_WriteHeadlessTrace("GameWindow.Open current_map=%s" % currentMap)
|
||||
if self.headlessGmEnabled:
|
||||
self.__HeadlessGMOnOpen(currentMap)
|
||||
|
||||
global cameraDistance, cameraPitch, cameraRotation, cameraHeight
|
||||
|
||||
@@ -385,7 +220,6 @@ class GameWindow(ui.ScriptWindow):
|
||||
self.currentCubeNPC = 0
|
||||
|
||||
def Close(self):
|
||||
_WriteHeadlessTrace("GameWindow.Close begin current_map=%s" % background.GetCurrentMapName())
|
||||
self.Hide()
|
||||
|
||||
global cameraDistance, cameraPitch, cameraRotation, cameraHeight
|
||||
@@ -464,7 +298,6 @@ class GameWindow(ui.ScriptWindow):
|
||||
app.HideCursor()
|
||||
|
||||
print("---------------------------------------------------------------------------- CLOSE GAME WINDOW")
|
||||
_WriteHeadlessTrace("GameWindow.Close end current_map=%s" % background.GetCurrentMapName())
|
||||
|
||||
def __BuildKeyDict(self):
|
||||
onPressKeyDict = {}
|
||||
@@ -1023,7 +856,6 @@ class GameWindow(ui.ScriptWindow):
|
||||
|
||||
# SHOW_LOCAL_MAP_NAME
|
||||
def ShowMapName(self, mapName, x, y):
|
||||
_WriteHeadlessTrace("ShowMapName map=%s x=%d y=%d" % (mapName, x, y))
|
||||
|
||||
if self.mapNameShower:
|
||||
self.mapNameShower.ShowMapName(mapName, x, y)
|
||||
@@ -1633,104 +1465,8 @@ class GameWindow(ui.ScriptWindow):
|
||||
def OnMouseMiddleButtonUp(self):
|
||||
player.SetMouseMiddleButtonState(player.MBS_CLICK)
|
||||
|
||||
def __HeadlessGMOnOpen(self, currentMap):
|
||||
global HEADLESS_GM_STATE
|
||||
|
||||
state = HEADLESS_GM_STATE
|
||||
now = app.GetTime()
|
||||
|
||||
if not state["initialized"]:
|
||||
state["steps"] = _GetHeadlessWarpSteps()
|
||||
state["index"] = 0
|
||||
state["phase"] = "waiting_command"
|
||||
state["command_at"] = now + _HeadlessGMCommandDelay()
|
||||
state["deadline"] = 0.0
|
||||
state["quit_requested"] = False
|
||||
state["initialized"] = True
|
||||
_WriteHeadlessTrace("GM ready current_map=%s steps=%d" % (currentMap, len(state["steps"])))
|
||||
|
||||
if not state["steps"]:
|
||||
state["phase"] = "failed"
|
||||
_HeadlessGMRequestQuit("No warp steps configured")
|
||||
return
|
||||
|
||||
if state["phase"] != "waiting_open":
|
||||
return
|
||||
|
||||
if state["index"] >= len(state["steps"]):
|
||||
state["phase"] = "success"
|
||||
_HeadlessGMRequestQuit("Scenario success current_map=%s" % currentMap)
|
||||
return
|
||||
|
||||
expectedMap = state["steps"][state["index"]]["map_name"]
|
||||
if currentMap != expectedMap:
|
||||
state["phase"] = "failed"
|
||||
_HeadlessGMRequestQuit("Warp open mismatch index=%d expected=%s current_map=%s" % (state["index"], expectedMap, currentMap))
|
||||
return
|
||||
|
||||
_WriteHeadlessTrace("Warp arrived index=%d map=%s" % (state["index"], currentMap))
|
||||
state["index"] += 1
|
||||
|
||||
if state["index"] >= len(state["steps"]):
|
||||
state["phase"] = "success"
|
||||
_HeadlessGMRequestQuit("Scenario success current_map=%s" % currentMap)
|
||||
return
|
||||
|
||||
state["phase"] = "settling"
|
||||
state["command_at"] = now + _HeadlessGMSettleDelay()
|
||||
state["deadline"] = 0.0
|
||||
|
||||
def __HeadlessGMOnUpdate(self):
|
||||
global HEADLESS_GM_STATE
|
||||
|
||||
if not self.headlessGmEnabled:
|
||||
return
|
||||
|
||||
state = HEADLESS_GM_STATE
|
||||
if not state["initialized"] or state["quit_requested"]:
|
||||
return
|
||||
|
||||
now = app.GetTime()
|
||||
|
||||
if state["phase"] == "waiting_command":
|
||||
if state["index"] >= len(state["steps"]):
|
||||
state["phase"] = "success"
|
||||
_HeadlessGMRequestQuit("Scenario success current_map=%s" % background.GetCurrentMapName())
|
||||
return
|
||||
|
||||
if now < state["command_at"]:
|
||||
return
|
||||
|
||||
if 0 == player.GetMainCharacterIndex():
|
||||
return
|
||||
|
||||
step = state["steps"][state["index"]]
|
||||
meterX = int(step["global_x"] / 100)
|
||||
meterY = int(step["global_y"] / 100)
|
||||
command = "/warp %d %d" % (meterX, meterY)
|
||||
_WriteHeadlessTrace("Warp send index=%d map=%s meter_x=%d meter_y=%d current_map=%s" % (state["index"], step["map_name"], meterX, meterY, background.GetCurrentMapName()))
|
||||
net.SendChatPacket(command)
|
||||
state["phase"] = "waiting_open"
|
||||
state["deadline"] = now + _HeadlessGMWarpTimeout()
|
||||
return
|
||||
|
||||
if state["phase"] == "settling":
|
||||
if now >= state["command_at"]:
|
||||
state["phase"] = "waiting_command"
|
||||
return
|
||||
|
||||
if state["phase"] == "waiting_open" and now > state["deadline"]:
|
||||
if state["index"] < len(state["steps"]):
|
||||
expectedMap = state["steps"][state["index"]]["map_name"]
|
||||
else:
|
||||
expectedMap = ""
|
||||
state["phase"] = "failed"
|
||||
_HeadlessGMRequestQuit("Warp timeout index=%d expected=%s current_map=%s" % (state["index"], expectedMap, background.GetCurrentMapName()))
|
||||
return
|
||||
|
||||
def OnUpdate(self):
|
||||
app.UpdateGame()
|
||||
self.__HeadlessGMOnUpdate()
|
||||
|
||||
if self.mapNameShower.IsShow():
|
||||
self.mapNameShower.Update()
|
||||
@@ -2493,3 +2229,4 @@ class GameWindow(ui.ScriptWindow):
|
||||
|
||||
def SkillClearCoolTime(self, slotIndex):
|
||||
self.interface.SkillClearCoolTime(slotIndex)
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import os
|
||||
|
||||
import ui
|
||||
import uiScriptLocale
|
||||
import net
|
||||
@@ -37,25 +35,6 @@ import uiOption
|
||||
import uiRestart
|
||||
####################################
|
||||
|
||||
|
||||
def _GetHeadlessScenario():
|
||||
return os.environ.get("M2_HEADLESS_SCENARIO", "").strip().lower()
|
||||
|
||||
|
||||
def _WriteHeadlessTrace(message):
|
||||
scenario = _GetHeadlessScenario()
|
||||
if scenario == "map_load":
|
||||
tracePath = "log/headless_map_load_trace.txt"
|
||||
elif scenario == "gm_teleport":
|
||||
tracePath = "log/headless_gm_teleport_trace.txt"
|
||||
else:
|
||||
return
|
||||
|
||||
try:
|
||||
open(tracePath, "a").write("%s\n" % message)
|
||||
except:
|
||||
pass
|
||||
|
||||
class LoadingWindow(ui.ScriptWindow):
|
||||
def __init__(self, stream):
|
||||
print("NEW LOADING WINDOW -------------------------------------------------------------------------------")
|
||||
@@ -239,7 +218,6 @@ class LoadingWindow(ui.ScriptWindow):
|
||||
try:
|
||||
runFunc()
|
||||
except:
|
||||
_WriteHeadlessTrace("LoadData failure step=%d" % progress)
|
||||
self.errMsg.Show()
|
||||
self.loadStepList=[]
|
||||
|
||||
@@ -324,9 +302,7 @@ class LoadingWindow(ui.ScriptWindow):
|
||||
emotion.RegisterEmotionIcons()
|
||||
|
||||
def __LoadMap(self):
|
||||
_WriteHeadlessTrace("LoadMap begin global_x=%d global_y=%d" % (self.playerX, self.playerY))
|
||||
net.Warp(self.playerX, self.playerY)
|
||||
_WriteHeadlessTrace("LoadMap current_map=%s" % background.GetCurrentMapName())
|
||||
|
||||
def __LoadSound(self):
|
||||
playerSettingModule.LoadGameData("SOUND")
|
||||
@@ -361,7 +337,6 @@ class LoadingWindow(ui.ScriptWindow):
|
||||
# END_OF_GUILD_BUILDING
|
||||
|
||||
def __StartGame(self):
|
||||
_WriteHeadlessTrace("StartGame begin current_map=%s" % background.GetCurrentMapName())
|
||||
background.SetViewDistanceSet(background.DISTANCE0, 25600)
|
||||
"""
|
||||
background.SetViewDistanceSet(background.DISTANCE1, 19200)
|
||||
@@ -374,7 +349,6 @@ class LoadingWindow(ui.ScriptWindow):
|
||||
app.SetGlobalCenterPosition(self.playerX, self.playerY)
|
||||
|
||||
net.StartGame()
|
||||
_WriteHeadlessTrace("StartGame queued current_map=%s" % background.GetCurrentMapName())
|
||||
|
||||
def _ReloadTitleNames():
|
||||
for i in range(len(localeInfo.TITLE_NAME_LIST)):
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import os
|
||||
import dbg
|
||||
import app
|
||||
import net
|
||||
@@ -19,10 +18,6 @@ import ime
|
||||
import uiScriptLocale
|
||||
import debugInfo
|
||||
|
||||
|
||||
def _AllowHeadlessLoginInfo():
|
||||
return os.environ.get("M2_HEADLESS_SCENARIO", "").strip().lower() == "gm_teleport"
|
||||
|
||||
# Multi-language hot-reload system
|
||||
from uilocaleselector import LocaleSelector
|
||||
|
||||
@@ -720,7 +715,7 @@ class LoginWindow(ui.ScriptWindow):
|
||||
|
||||
def __LoadLoginInfo(self, loginInfoFileName):
|
||||
# This should not work in production
|
||||
if not debugInfo.IsDebugMode() and not _AllowHeadlessLoginInfo():
|
||||
if not debugInfo.IsDebugMode():
|
||||
app.loggined = FALSE
|
||||
else:
|
||||
try:
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
###################################################################################################
|
||||
# Network
|
||||
|
||||
import os
|
||||
|
||||
import app
|
||||
import chr
|
||||
import dbg
|
||||
@@ -20,25 +18,6 @@ import uiPhaseCurtain
|
||||
|
||||
import localeInfo
|
||||
|
||||
|
||||
def _GetHeadlessScenario():
|
||||
return os.environ.get("M2_HEADLESS_SCENARIO", "").strip().lower()
|
||||
|
||||
|
||||
def _WriteHeadlessTrace(message):
|
||||
scenario = _GetHeadlessScenario()
|
||||
if scenario == "map_load":
|
||||
tracePath = "log/headless_map_load_trace.txt"
|
||||
elif scenario == "gm_teleport":
|
||||
tracePath = "log/headless_gm_teleport_trace.txt"
|
||||
else:
|
||||
return
|
||||
|
||||
try:
|
||||
open(tracePath, "a").write("%s\n" % message)
|
||||
except:
|
||||
pass
|
||||
|
||||
class PopupDialog(ui.ScriptWindow):
|
||||
# MR-15: Multiline dialog messages
|
||||
BASE_HEIGHT = 105
|
||||
@@ -188,7 +167,6 @@ class MainStream(object):
|
||||
|
||||
if newPhaseWindow:
|
||||
newPhaseWindow.Open()
|
||||
_WriteHeadlessTrace("MainStream.ChangePhase opened=%s" % newPhaseWindow.__class__.__name__)
|
||||
|
||||
self.curPhaseWindow=newPhaseWindow
|
||||
|
||||
@@ -259,7 +237,7 @@ class MainStream(object):
|
||||
try:
|
||||
import introLoading
|
||||
loadingPhaseWindow=introLoading.LoadingWindow(self)
|
||||
loadingPhaseWindow.DEBUG_LoadData(x, y)
|
||||
loadingPhaseWindow.LoadData(x, y)
|
||||
self.SetPhaseWindow(loadingPhaseWindow)
|
||||
except:
|
||||
import exception
|
||||
@@ -278,10 +256,8 @@ class MainStream(object):
|
||||
def SetGamePhase(self):
|
||||
try:
|
||||
import game
|
||||
_WriteHeadlessTrace("MainStream.SetGamePhase begin current_map=%s" % background.GetCurrentMapName())
|
||||
self.popupWindow.Close()
|
||||
self.SetPhaseWindow(game.GameWindow(self))
|
||||
_WriteHeadlessTrace("MainStream.SetGamePhase queued current_map=%s" % background.GetCurrentMapName())
|
||||
except:
|
||||
raise
|
||||
import exception
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import os
|
||||
|
||||
import dbg
|
||||
import app
|
||||
import localeInfo
|
||||
@@ -16,51 +14,6 @@ import stringCommander
|
||||
|
||||
#bind_me(locals().values())
|
||||
|
||||
|
||||
def _GetHeadlessScenario():
|
||||
return os.environ.get("M2_HEADLESS_SCENARIO", "").strip().lower()
|
||||
|
||||
|
||||
def _WriteHeadlessTrace(message):
|
||||
scenario = _GetHeadlessScenario()
|
||||
if scenario == "map_load":
|
||||
tracePath = "log/headless_map_load_trace.txt"
|
||||
elif scenario == "gm_teleport":
|
||||
tracePath = "log/headless_gm_teleport_trace.txt"
|
||||
else:
|
||||
return
|
||||
|
||||
try:
|
||||
open(tracePath, "a").write("%s\n" % message)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def _GetHeadlessInt(name, default):
|
||||
try:
|
||||
return int(os.environ.get(name, str(default)))
|
||||
except (TypeError, ValueError):
|
||||
return default
|
||||
|
||||
|
||||
def _SetInitialPhase(mainStream):
|
||||
scenario = _GetHeadlessScenario()
|
||||
if scenario == "map_load":
|
||||
mapName = os.environ.get("M2_HEADLESS_MAP_NAME", "").strip()
|
||||
globalX = _GetHeadlessInt("M2_HEADLESS_GLOBAL_X", 460800)
|
||||
globalY = _GetHeadlessInt("M2_HEADLESS_GLOBAL_Y", 960000)
|
||||
|
||||
_WriteHeadlessTrace("Scenario begin map=%s global_x=%d global_y=%d" % (mapName, globalX, globalY))
|
||||
mainStream.SetTestGamePhase(globalX, globalY)
|
||||
return
|
||||
|
||||
if scenario == "gm_teleport":
|
||||
_WriteHeadlessTrace("Scenario begin gm_teleport")
|
||||
mainStream.SetLoginPhase()
|
||||
return
|
||||
|
||||
mainStream.SetLoginPhase()
|
||||
|
||||
def RunApp():
|
||||
musicInfo.LoadLastPlayFieldMusic()
|
||||
|
||||
@@ -94,7 +47,8 @@ def RunApp():
|
||||
mainStream.Create()
|
||||
|
||||
#mainStream.SetLoadingPhase()
|
||||
_SetInitialPhase(mainStream)
|
||||
|
||||
mainStream.SetLoginPhase()
|
||||
#mainStream.SetSelectCharacterPhase()
|
||||
#mainStream.SetCreateCharacterPhase()
|
||||
#mainStream.SetSelectEmpirePhase()
|
||||
@@ -104,3 +58,4 @@ def RunApp():
|
||||
mainStream.Destroy()
|
||||
|
||||
RunApp()
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,5 +1,5 @@
|
||||
ScriptType CharacterSoundInformation
|
||||
|
||||
SoundDataCount 2
|
||||
SoundData00 0.231000 "sound/pc2/assassin/dualhand_sword/combo4.wav"
|
||||
SoundData01 0.198000 "sound/common/swing/a_dh_c_4.wav"
|
||||
SoundData00 0.066000 "sound/pc2/assassin/dualhand_sword/combo7.wav"
|
||||
SoundData01 0.033000 "sound/common/swing/w_1h_c_2.wav"
|
||||
|
||||
@@ -163,14 +163,23 @@ Files under `.updates/` are created by the launcher. The user shouldn't touch th
|
||||
|
||||
1. On a trusted machine (not random laptop), with the private signing key present:
|
||||
```bash
|
||||
./scripts/make-release.sh --version 2026.04.14-1 --source /path/to/fresh/client
|
||||
./scripts/make-release.sh --source /path/to/fresh/client --version 2026.04.14-1 \
|
||||
--previous 2026.04.13-3 --notes notes.md --dry-run
|
||||
```
|
||||
2. The script walks the client directory, computes sha256 for each file, writes a `manifest.json`, signs it, and produces a release directory `release/2026.04.14-1/` containing the manifest, its signature, and only the new blobs (ones not already present on the server).
|
||||
[`scripts/make-release.sh`](../scripts/make-release.sh) is the single entry
|
||||
point for the v1 manual flow. It drives `make-manifest.py` + `sign-manifest.py`,
|
||||
builds the content-addressed blob tree under `files/<hash[0:2]>/<hash>` with
|
||||
hardlink-based deduplication, archives the signed manifest into
|
||||
`manifests/<version>.json`, and — unless `--dry-run` is passed — rsyncs the
|
||||
blob tree first and the `manifest.json` + `manifest.json.sig` pair last so the
|
||||
release becomes visible atomically. Flags: `--key` (default
|
||||
`~/.config/metin/launcher-signing-key`, must be mode 600), `--out` (default
|
||||
`/tmp/release-<version>`), `--force` to overwrite a non-empty out dir, `--yes`
|
||||
to skip the interactive rsync confirmation, `--rsync-target <user@host:/path>`
|
||||
to override the upload destination.
|
||||
2. The script walks the client directory, computes sha256 for each file, writes a `manifest.json`, signs it, and produces a release directory containing the manifest, its signature, and the deduplicated blob tree.
|
||||
3. Human review: diff the new manifest against the previous one, sanity-check size and file count.
|
||||
4. `rsync` the release directory to the VPS:
|
||||
```bash
|
||||
rsync -av release/2026.04.14-1/ mt2.jakubkadlec.dev@mt2.jakubkadlec.dev:/var/www/updates.jakubkadlec.dev/
|
||||
```
|
||||
4. Re-run without `--dry-run` (same args) to rsync to the VPS. The script prints the target and waits for confirmation unless `--yes` is passed.
|
||||
5. Verify from a second machine: `curl` the manifest, check signature, check a random blob.
|
||||
6. Tag the release in git.
|
||||
|
||||
|
||||
169
scripts/make-release.sh
Executable file
169
scripts/make-release.sh
Executable file
@@ -0,0 +1,169 @@
|
||||
#!/usr/bin/env bash
|
||||
# make-release.sh — assemble, sign, and (optionally) publish a client release.
|
||||
#
|
||||
# Drives scripts/make-manifest.py + scripts/sign-manifest.py, then builds the
|
||||
# content-addressed blob tree the launcher pulls from. See docs/update-manager.md
|
||||
# for the end-to-end design; this script is the v1 manual publishing flow.
|
||||
#
|
||||
# Usage:
|
||||
# scripts/make-release.sh --source <client-dir> --version <version> \
|
||||
# [--previous <version>] [--notes <file>] \
|
||||
# [--key <path>] [--out <path>] [--force] \
|
||||
# [--dry-run] [--yes] [--rsync-target <user@host:/path>]
|
||||
set -euo pipefail
|
||||
|
||||
# -------- arg parsing --------
|
||||
SOURCE=""
|
||||
VERSION=""
|
||||
PREVIOUS=""
|
||||
NOTES_FILE=""
|
||||
KEY="${HOME}/.config/metin/launcher-signing-key"
|
||||
OUT=""
|
||||
FORCE=0
|
||||
DRY_RUN=0
|
||||
YES=0
|
||||
RSYNC_TARGET="mt2.jakubkadlec.dev@mt2.jakubkadlec.dev:/var/www/updates.jakubkadlec.dev/"
|
||||
|
||||
die() { echo "error: $*" >&2; exit 1; }
|
||||
say() { echo "[make-release] $*"; }
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--source) SOURCE="$2"; shift 2 ;;
|
||||
--version) VERSION="$2"; shift 2 ;;
|
||||
--previous) PREVIOUS="$2"; shift 2 ;;
|
||||
--notes) NOTES_FILE="$2"; shift 2 ;;
|
||||
--key) KEY="$2"; shift 2 ;;
|
||||
--out) OUT="$2"; shift 2 ;;
|
||||
--force) FORCE=1; shift ;;
|
||||
--dry-run) DRY_RUN=1; shift ;;
|
||||
--yes) YES=1; shift ;;
|
||||
--rsync-target) RSYNC_TARGET="$2"; shift 2 ;;
|
||||
-h|--help) sed -n '1,15p' "$0"; exit 0 ;;
|
||||
*) die "unknown arg: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -n "$SOURCE" ]] || die "--source is required"
|
||||
[[ -n "$VERSION" ]] || die "--version is required"
|
||||
[[ -d "$SOURCE" ]] || die "source dir does not exist: $SOURCE"
|
||||
[[ -f "$SOURCE/Metin2.exe" ]] || die "source does not look like a client dir (missing Metin2.exe): $SOURCE"
|
||||
[[ -f "$KEY" ]] || die "signing key not found: $KEY"
|
||||
|
||||
KEY_MODE=$(stat -c '%a' "$KEY")
|
||||
[[ "$KEY_MODE" == "600" ]] || die "signing key $KEY must be mode 600, got $KEY_MODE"
|
||||
|
||||
[[ -n "$NOTES_FILE" && ! -f "$NOTES_FILE" ]] && die "notes file not found: $NOTES_FILE"
|
||||
|
||||
: "${OUT:=/tmp/release-${VERSION}}"
|
||||
SOURCE=$(cd "$SOURCE" && pwd)
|
||||
OUT_ABS=$(mkdir -p "$OUT" && cd "$OUT" && pwd)
|
||||
|
||||
if [[ -n "$(ls -A "$OUT_ABS" 2>/dev/null)" && "$FORCE" -ne 1 ]]; then
|
||||
die "output directory $OUT_ABS is non-empty (use --force to overwrite)"
|
||||
fi
|
||||
|
||||
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
|
||||
say "source: $SOURCE"
|
||||
say "version: $VERSION"
|
||||
say "out: $OUT_ABS"
|
||||
say "key: $KEY"
|
||||
|
||||
# -------- [1/6] manifest --------
|
||||
say "[1/6] building manifest"
|
||||
mkdir -p "$OUT_ABS/manifests" "$OUT_ABS/files"
|
||||
MANIFEST="$OUT_ABS/manifest.json"
|
||||
|
||||
mk_args=(--source "$SOURCE" --version "$VERSION" --out "$MANIFEST")
|
||||
[[ -n "$PREVIOUS" ]] && mk_args+=(--previous "$PREVIOUS")
|
||||
if [[ -n "$NOTES_FILE" ]]; then
|
||||
notes_text=$(cat "$NOTES_FILE")
|
||||
mk_args+=(--notes "$notes_text")
|
||||
fi
|
||||
python3 "$SCRIPT_DIR/make-manifest.py" "${mk_args[@]}"
|
||||
|
||||
# -------- [2/6] sign --------
|
||||
say "[2/6] signing manifest"
|
||||
python3 "$SCRIPT_DIR/sign-manifest.py" --manifest "$MANIFEST" --key "$KEY"
|
||||
SIG="$MANIFEST.sig"
|
||||
[[ -f "$SIG" ]] || die "signature not produced"
|
||||
sig_len=$(stat -c '%s' "$SIG")
|
||||
[[ "$sig_len" == "64" ]] || die "signature is $sig_len bytes, expected 64"
|
||||
|
||||
# -------- [3/6] archive historical manifest --------
|
||||
say "[3/6] archiving historical manifest -> manifests/${VERSION}.json"
|
||||
cp -f "$MANIFEST" "$OUT_ABS/manifests/${VERSION}.json"
|
||||
cp -f "$SIG" "$OUT_ABS/manifests/${VERSION}.json.sig"
|
||||
|
||||
# -------- [4/6] blob tree --------
|
||||
say "[4/6] building content-addressed blob tree"
|
||||
|
||||
# Extract (path, sha256) pairs for launcher + every file entry.
|
||||
mapfile -t PAIRS < <(jq -r '
|
||||
([.launcher] + .files)
|
||||
| .[]
|
||||
| "\(.sha256)\t\(.path)"
|
||||
' "$MANIFEST")
|
||||
|
||||
total_entries=${#PAIRS[@]}
|
||||
unique_count=0
|
||||
dedup_count=0
|
||||
bytes_written=0
|
||||
|
||||
declare -A SEEN
|
||||
for pair in "${PAIRS[@]}"; do
|
||||
hash="${pair%%$'\t'*}"
|
||||
rel="${pair#*$'\t'}"
|
||||
src="$SOURCE/$rel"
|
||||
[[ -f "$src" ]] || die "file in manifest missing from source: $rel"
|
||||
if [[ -n "${SEEN[$hash]:-}" ]]; then
|
||||
dedup_count=$((dedup_count + 1))
|
||||
continue
|
||||
fi
|
||||
SEEN[$hash]=1
|
||||
unique_count=$((unique_count + 1))
|
||||
prefix="${hash:0:2}"
|
||||
dst_dir="$OUT_ABS/files/$prefix"
|
||||
dst="$dst_dir/$hash"
|
||||
mkdir -p "$dst_dir"
|
||||
if [[ -f "$dst" ]]; then
|
||||
continue
|
||||
fi
|
||||
# Try hardlink first, fall back to copy across filesystems.
|
||||
if ! cp -l "$src" "$dst" 2>/dev/null; then
|
||||
cp "$src" "$dst"
|
||||
fi
|
||||
sz=$(stat -c '%s' "$dst")
|
||||
bytes_written=$((bytes_written + sz))
|
||||
done
|
||||
|
||||
say " entries: $total_entries unique blobs: $unique_count deduped: $dedup_count"
|
||||
say " bytes written: $bytes_written"
|
||||
|
||||
# -------- [5/6] layout summary --------
|
||||
say "[5/6] final layout:"
|
||||
(cd "$OUT_ABS" && find . -maxdepth 2 -mindepth 1 -printf ' %p\n' | sort | head -40)
|
||||
|
||||
# -------- [6/6] rsync --------
|
||||
if [[ "$DRY_RUN" -eq 1 ]]; then
|
||||
say "[6/6] --dry-run set, skipping rsync. target would be: $RSYNC_TARGET"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
say "[6/6] rsync target: $RSYNC_TARGET"
|
||||
if [[ "$YES" -ne 1 ]]; then
|
||||
read -r -p "continue? [y/N] " ans
|
||||
[[ "$ans" == "y" || "$ans" == "Y" ]] || die "aborted by user"
|
||||
fi
|
||||
|
||||
# Stage 1: everything except manifest.json(.sig) — blobs and historical archive.
|
||||
rsync -av --delay-updates --checksum --omit-dir-times --no-perms \
|
||||
--exclude 'manifest.json' --exclude 'manifest.json.sig' \
|
||||
"$OUT_ABS"/ "$RSYNC_TARGET"
|
||||
|
||||
# Stage 2: manifest + signature, so the new release becomes visible last.
|
||||
rsync -av --checksum --omit-dir-times --no-perms \
|
||||
"$MANIFEST" "$SIG" "$RSYNC_TARGET"
|
||||
|
||||
say "done."
|
||||
Reference in New Issue
Block a user