forked from metin-server/m2dev-client
Compare commits
8 Commits
claude/mak
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
403dddd6af | ||
|
|
10915467c1 | ||
|
|
780900af61 | ||
|
|
b9065ca8d2 | ||
|
|
8767a2b3ac | ||
|
|
0edaea5993 | ||
|
|
5e79fc27e1 | ||
|
|
95fc2df7c0 |
@@ -1,524 +0,0 @@
|
|||||||
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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,654 +0,0 @@
|
|||||||
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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
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
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
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
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
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
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BIN
assets/Effect/ymir work/effect/etc/compete/ready.dds
Normal file
BIN
assets/Effect/ymir work/effect/etc/compete/ready.dds
Normal file
Binary file not shown.
BIN
assets/Effect/ymir work/effect/monster2/smoke_dust.dds
Normal file
BIN
assets/Effect/ymir work/effect/monster2/smoke_dust.dds
Normal file
Binary file not shown.
@@ -1,5 +1,4 @@
|
|||||||
ScriptType MotionData
|
ScriptType MotionData
|
||||||
|
|
||||||
MotionFileName "D:\Ymir Work\monster\orc_lord\32_1.GR2"
|
MotionFileName "D:\Ymir Work\monster\orc_lord\30_1.GR2"
|
||||||
MotionDuration 0.833333
|
MotionDuration 0.833333
|
||||||
|
|
||||||
|
|||||||
BIN
assets/Sound/sound/common/walk_grass_n.wav
Normal file
BIN
assets/Sound/sound/common/walk_grass_n.wav
Normal file
Binary file not shown.
BIN
assets/Sound/sound/monster/bou/bou_swing1.wav
Normal file
BIN
assets/Sound/sound/monster/bou/bou_swing1.wav
Normal file
Binary file not shown.
BIN
assets/Sound/sound/monster/chuhen/club_attack.wav
Normal file
BIN
assets/Sound/sound/monster/chuhen/club_attack.wav
Normal file
Binary file not shown.
BIN
assets/Sound/sound/monster/gupae/gup_swing2.wav
Normal file
BIN
assets/Sound/sound/monster/gupae/gup_swing2.wav
Normal file
Binary file not shown.
BIN
assets/Sound/sound/monster/gupae/gup_swing3.wav
Normal file
BIN
assets/Sound/sound/monster/gupae/gup_swing3.wav
Normal file
Binary file not shown.
BIN
assets/Sound/sound/monster/maenghwan/mah_swing1.wav
Normal file
BIN
assets/Sound/sound/monster/maenghwan/mah_swing1.wav
Normal file
Binary file not shown.
BIN
assets/Sound/sound/monster/misterious_diseased_boss/damage_1.wav
Normal file
BIN
assets/Sound/sound/monster/misterious_diseased_boss/damage_1.wav
Normal file
Binary file not shown.
BIN
assets/Sound/sound/monster/thief1/th1_act2.wav
Normal file
BIN
assets/Sound/sound/monster/thief1/th1_act2.wav
Normal file
Binary file not shown.
BIN
assets/Sound/sound/monster/thief1/th1_swing2.wav
Normal file
BIN
assets/Sound/sound/monster/thief1/th1_swing2.wav
Normal file
Binary file not shown.
BIN
assets/Sound/sound/monster/thief1/th1_swing3.wav
Normal file
BIN
assets/Sound/sound/monster/thief1/th1_swing3.wav
Normal file
Binary file not shown.
BIN
assets/Sound/sound/monster/thief2/th2_swing2.wav
Normal file
BIN
assets/Sound/sound/monster/thief2/th2_swing2.wav
Normal file
Binary file not shown.
BIN
assets/Sound/sound/monster/thief2/th2_swing3.wav
Normal file
BIN
assets/Sound/sound/monster/thief2/th2_swing3.wav
Normal file
Binary file not shown.
BIN
assets/Sound/sound/monster/thiefboss1/thb1_swing2.wav
Normal file
BIN
assets/Sound/sound/monster/thiefboss1/thb1_swing2.wav
Normal file
Binary file not shown.
BIN
assets/Sound/sound/monster/thiefboss2/thb2_swing2.wav
Normal file
BIN
assets/Sound/sound/monster/thiefboss2/thb2_swing2.wav
Normal file
Binary file not shown.
BIN
assets/Sound/sound/monster/thiefboss2/thb2_swing3.wav
Normal file
BIN
assets/Sound/sound/monster/thiefboss2/thb2_swing3.wav
Normal file
Binary file not shown.
BIN
assets/Sound/sound/monster/thiefboss3/thb3_swing2.wav
Normal file
BIN
assets/Sound/sound/monster/thiefboss3/thb3_swing2.wav
Normal file
Binary file not shown.
BIN
assets/Sound/sound/pc/sura/general/attack_1.wav
Normal file
BIN
assets/Sound/sound/pc/sura/general/attack_1.wav
Normal file
Binary file not shown.
BIN
assets/Sound/sound/pc/sura/general/attack_2.wav
Normal file
BIN
assets/Sound/sound/pc/sura/general/attack_2.wav
Normal file
Binary file not shown.
BIN
assets/Sound/sound/pc/sura/general/attack_3.wav
Normal file
BIN
assets/Sound/sound/pc/sura/general/attack_3.wav
Normal file
Binary file not shown.
BIN
assets/Sound/sound/pc/sura/general/swing_3.wav
Normal file
BIN
assets/Sound/sound/pc/sura/general/swing_3.wav
Normal file
Binary file not shown.
BIN
assets/Sound/sound/pc/sura/skill/horse_splash.wav
Normal file
BIN
assets/Sound/sound/pc/sura/skill/horse_splash.wav
Normal file
Binary file not shown.
Binary file not shown.
@@ -55,6 +55,157 @@ from _weakref import proxy
|
|||||||
SCREENSHOT_CWDSAVE = False
|
SCREENSHOT_CWDSAVE = False
|
||||||
SCREENSHOT_DIR = None
|
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
|
cameraDistance = 1550.0
|
||||||
cameraPitch = 27.0
|
cameraPitch = 27.0
|
||||||
cameraRotation = 0.0
|
cameraRotation = 0.0
|
||||||
@@ -64,6 +215,7 @@ testAlignment = 0
|
|||||||
|
|
||||||
class GameWindow(ui.ScriptWindow):
|
class GameWindow(ui.ScriptWindow):
|
||||||
def __init__(self, stream):
|
def __init__(self, stream):
|
||||||
|
_WriteHeadlessTrace("GameWindow.__init__ begin")
|
||||||
ui.ScriptWindow.__init__(self, "GAME")
|
ui.ScriptWindow.__init__(self, "GAME")
|
||||||
self.SetWindowName("game")
|
self.SetWindowName("game")
|
||||||
net.SetPhaseWindow(net.PHASE_WINDOW_GAME, self)
|
net.SetPhaseWindow(net.PHASE_WINDOW_GAME, self)
|
||||||
@@ -72,6 +224,7 @@ class GameWindow(ui.ScriptWindow):
|
|||||||
self.quickSlotPageIndex = 0
|
self.quickSlotPageIndex = 0
|
||||||
self.lastPKModeSendedTime = 0
|
self.lastPKModeSendedTime = 0
|
||||||
self.pressNumber = None
|
self.pressNumber = None
|
||||||
|
self.headlessGmEnabled = _HeadlessGMEnabled()
|
||||||
|
|
||||||
self.guildWarQuestionDialog = None
|
self.guildWarQuestionDialog = None
|
||||||
self.interface = None
|
self.interface = None
|
||||||
@@ -82,9 +235,16 @@ class GameWindow(ui.ScriptWindow):
|
|||||||
self.playerGauge = None
|
self.playerGauge = None
|
||||||
|
|
||||||
self.stream = stream
|
self.stream = stream
|
||||||
self.interface = interfaceModule.Interface()
|
if self.headlessGmEnabled:
|
||||||
self.interface.MakeInterface()
|
self.interface = _HeadlessInterface()
|
||||||
self.interface.ShowDefaultWindows()
|
_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 = uiPhaseCurtain.PhaseCurtain()
|
||||||
self.curtain.speed = 0.03
|
self.curtain.speed = 0.03
|
||||||
@@ -112,6 +272,7 @@ class GameWindow(ui.ScriptWindow):
|
|||||||
|
|
||||||
self.__ServerCommand_Build()
|
self.__ServerCommand_Build()
|
||||||
self.__ProcessPreservedServerCommand()
|
self.__ProcessPreservedServerCommand()
|
||||||
|
_WriteHeadlessTrace("GameWindow.__init__ done")
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
player.SetGameWindow(0)
|
player.SetGameWindow(0)
|
||||||
@@ -133,6 +294,10 @@ class GameWindow(ui.ScriptWindow):
|
|||||||
self.enableXMasBoom = False
|
self.enableXMasBoom = False
|
||||||
self.startTimeXMasBoom = 0.0
|
self.startTimeXMasBoom = 0.0
|
||||||
self.indexXMasBoom = 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
|
global cameraDistance, cameraPitch, cameraRotation, cameraHeight
|
||||||
|
|
||||||
@@ -220,6 +385,7 @@ class GameWindow(ui.ScriptWindow):
|
|||||||
self.currentCubeNPC = 0
|
self.currentCubeNPC = 0
|
||||||
|
|
||||||
def Close(self):
|
def Close(self):
|
||||||
|
_WriteHeadlessTrace("GameWindow.Close begin current_map=%s" % background.GetCurrentMapName())
|
||||||
self.Hide()
|
self.Hide()
|
||||||
|
|
||||||
global cameraDistance, cameraPitch, cameraRotation, cameraHeight
|
global cameraDistance, cameraPitch, cameraRotation, cameraHeight
|
||||||
@@ -298,6 +464,7 @@ class GameWindow(ui.ScriptWindow):
|
|||||||
app.HideCursor()
|
app.HideCursor()
|
||||||
|
|
||||||
print("---------------------------------------------------------------------------- CLOSE GAME WINDOW")
|
print("---------------------------------------------------------------------------- CLOSE GAME WINDOW")
|
||||||
|
_WriteHeadlessTrace("GameWindow.Close end current_map=%s" % background.GetCurrentMapName())
|
||||||
|
|
||||||
def __BuildKeyDict(self):
|
def __BuildKeyDict(self):
|
||||||
onPressKeyDict = {}
|
onPressKeyDict = {}
|
||||||
@@ -856,6 +1023,7 @@ class GameWindow(ui.ScriptWindow):
|
|||||||
|
|
||||||
# SHOW_LOCAL_MAP_NAME
|
# SHOW_LOCAL_MAP_NAME
|
||||||
def ShowMapName(self, mapName, x, y):
|
def ShowMapName(self, mapName, x, y):
|
||||||
|
_WriteHeadlessTrace("ShowMapName map=%s x=%d y=%d" % (mapName, x, y))
|
||||||
|
|
||||||
if self.mapNameShower:
|
if self.mapNameShower:
|
||||||
self.mapNameShower.ShowMapName(mapName, x, y)
|
self.mapNameShower.ShowMapName(mapName, x, y)
|
||||||
@@ -1465,8 +1633,104 @@ class GameWindow(ui.ScriptWindow):
|
|||||||
def OnMouseMiddleButtonUp(self):
|
def OnMouseMiddleButtonUp(self):
|
||||||
player.SetMouseMiddleButtonState(player.MBS_CLICK)
|
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):
|
def OnUpdate(self):
|
||||||
app.UpdateGame()
|
app.UpdateGame()
|
||||||
|
self.__HeadlessGMOnUpdate()
|
||||||
|
|
||||||
if self.mapNameShower.IsShow():
|
if self.mapNameShower.IsShow():
|
||||||
self.mapNameShower.Update()
|
self.mapNameShower.Update()
|
||||||
@@ -2229,4 +2493,3 @@ class GameWindow(ui.ScriptWindow):
|
|||||||
|
|
||||||
def SkillClearCoolTime(self, slotIndex):
|
def SkillClearCoolTime(self, slotIndex):
|
||||||
self.interface.SkillClearCoolTime(slotIndex)
|
self.interface.SkillClearCoolTime(slotIndex)
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
import ui
|
import ui
|
||||||
import uiScriptLocale
|
import uiScriptLocale
|
||||||
import net
|
import net
|
||||||
@@ -35,6 +37,25 @@ import uiOption
|
|||||||
import uiRestart
|
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):
|
class LoadingWindow(ui.ScriptWindow):
|
||||||
def __init__(self, stream):
|
def __init__(self, stream):
|
||||||
print("NEW LOADING WINDOW -------------------------------------------------------------------------------")
|
print("NEW LOADING WINDOW -------------------------------------------------------------------------------")
|
||||||
@@ -218,6 +239,7 @@ class LoadingWindow(ui.ScriptWindow):
|
|||||||
try:
|
try:
|
||||||
runFunc()
|
runFunc()
|
||||||
except:
|
except:
|
||||||
|
_WriteHeadlessTrace("LoadData failure step=%d" % progress)
|
||||||
self.errMsg.Show()
|
self.errMsg.Show()
|
||||||
self.loadStepList=[]
|
self.loadStepList=[]
|
||||||
|
|
||||||
@@ -302,7 +324,9 @@ class LoadingWindow(ui.ScriptWindow):
|
|||||||
emotion.RegisterEmotionIcons()
|
emotion.RegisterEmotionIcons()
|
||||||
|
|
||||||
def __LoadMap(self):
|
def __LoadMap(self):
|
||||||
|
_WriteHeadlessTrace("LoadMap begin global_x=%d global_y=%d" % (self.playerX, self.playerY))
|
||||||
net.Warp(self.playerX, self.playerY)
|
net.Warp(self.playerX, self.playerY)
|
||||||
|
_WriteHeadlessTrace("LoadMap current_map=%s" % background.GetCurrentMapName())
|
||||||
|
|
||||||
def __LoadSound(self):
|
def __LoadSound(self):
|
||||||
playerSettingModule.LoadGameData("SOUND")
|
playerSettingModule.LoadGameData("SOUND")
|
||||||
@@ -337,6 +361,7 @@ class LoadingWindow(ui.ScriptWindow):
|
|||||||
# END_OF_GUILD_BUILDING
|
# END_OF_GUILD_BUILDING
|
||||||
|
|
||||||
def __StartGame(self):
|
def __StartGame(self):
|
||||||
|
_WriteHeadlessTrace("StartGame begin current_map=%s" % background.GetCurrentMapName())
|
||||||
background.SetViewDistanceSet(background.DISTANCE0, 25600)
|
background.SetViewDistanceSet(background.DISTANCE0, 25600)
|
||||||
"""
|
"""
|
||||||
background.SetViewDistanceSet(background.DISTANCE1, 19200)
|
background.SetViewDistanceSet(background.DISTANCE1, 19200)
|
||||||
@@ -349,6 +374,7 @@ class LoadingWindow(ui.ScriptWindow):
|
|||||||
app.SetGlobalCenterPosition(self.playerX, self.playerY)
|
app.SetGlobalCenterPosition(self.playerX, self.playerY)
|
||||||
|
|
||||||
net.StartGame()
|
net.StartGame()
|
||||||
|
_WriteHeadlessTrace("StartGame queued current_map=%s" % background.GetCurrentMapName())
|
||||||
|
|
||||||
def _ReloadTitleNames():
|
def _ReloadTitleNames():
|
||||||
for i in range(len(localeInfo.TITLE_NAME_LIST)):
|
for i in range(len(localeInfo.TITLE_NAME_LIST)):
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import os
|
||||||
import dbg
|
import dbg
|
||||||
import app
|
import app
|
||||||
import net
|
import net
|
||||||
@@ -18,6 +19,10 @@ import ime
|
|||||||
import uiScriptLocale
|
import uiScriptLocale
|
||||||
import debugInfo
|
import debugInfo
|
||||||
|
|
||||||
|
|
||||||
|
def _AllowHeadlessLoginInfo():
|
||||||
|
return os.environ.get("M2_HEADLESS_SCENARIO", "").strip().lower() == "gm_teleport"
|
||||||
|
|
||||||
# Multi-language hot-reload system
|
# Multi-language hot-reload system
|
||||||
from uilocaleselector import LocaleSelector
|
from uilocaleselector import LocaleSelector
|
||||||
|
|
||||||
@@ -715,7 +720,7 @@ class LoginWindow(ui.ScriptWindow):
|
|||||||
|
|
||||||
def __LoadLoginInfo(self, loginInfoFileName):
|
def __LoadLoginInfo(self, loginInfoFileName):
|
||||||
# This should not work in production
|
# This should not work in production
|
||||||
if not debugInfo.IsDebugMode():
|
if not debugInfo.IsDebugMode() and not _AllowHeadlessLoginInfo():
|
||||||
app.loggined = FALSE
|
app.loggined = FALSE
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
###################################################################################################
|
###################################################################################################
|
||||||
# Network
|
# Network
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
import app
|
import app
|
||||||
import chr
|
import chr
|
||||||
import dbg
|
import dbg
|
||||||
@@ -18,6 +20,25 @@ import uiPhaseCurtain
|
|||||||
|
|
||||||
import localeInfo
|
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):
|
class PopupDialog(ui.ScriptWindow):
|
||||||
# MR-15: Multiline dialog messages
|
# MR-15: Multiline dialog messages
|
||||||
BASE_HEIGHT = 105
|
BASE_HEIGHT = 105
|
||||||
@@ -167,6 +188,7 @@ class MainStream(object):
|
|||||||
|
|
||||||
if newPhaseWindow:
|
if newPhaseWindow:
|
||||||
newPhaseWindow.Open()
|
newPhaseWindow.Open()
|
||||||
|
_WriteHeadlessTrace("MainStream.ChangePhase opened=%s" % newPhaseWindow.__class__.__name__)
|
||||||
|
|
||||||
self.curPhaseWindow=newPhaseWindow
|
self.curPhaseWindow=newPhaseWindow
|
||||||
|
|
||||||
@@ -237,7 +259,7 @@ class MainStream(object):
|
|||||||
try:
|
try:
|
||||||
import introLoading
|
import introLoading
|
||||||
loadingPhaseWindow=introLoading.LoadingWindow(self)
|
loadingPhaseWindow=introLoading.LoadingWindow(self)
|
||||||
loadingPhaseWindow.LoadData(x, y)
|
loadingPhaseWindow.DEBUG_LoadData(x, y)
|
||||||
self.SetPhaseWindow(loadingPhaseWindow)
|
self.SetPhaseWindow(loadingPhaseWindow)
|
||||||
except:
|
except:
|
||||||
import exception
|
import exception
|
||||||
@@ -256,8 +278,10 @@ class MainStream(object):
|
|||||||
def SetGamePhase(self):
|
def SetGamePhase(self):
|
||||||
try:
|
try:
|
||||||
import game
|
import game
|
||||||
|
_WriteHeadlessTrace("MainStream.SetGamePhase begin current_map=%s" % background.GetCurrentMapName())
|
||||||
self.popupWindow.Close()
|
self.popupWindow.Close()
|
||||||
self.SetPhaseWindow(game.GameWindow(self))
|
self.SetPhaseWindow(game.GameWindow(self))
|
||||||
|
_WriteHeadlessTrace("MainStream.SetGamePhase queued current_map=%s" % background.GetCurrentMapName())
|
||||||
except:
|
except:
|
||||||
raise
|
raise
|
||||||
import exception
|
import exception
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
import dbg
|
import dbg
|
||||||
import app
|
import app
|
||||||
import localeInfo
|
import localeInfo
|
||||||
@@ -14,6 +16,66 @@ import stringCommander
|
|||||||
|
|
||||||
#bind_me(locals().values())
|
#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 _ApplyRenderFPSOverride():
|
||||||
|
rawValue = os.environ.get("M2_RENDER_FPS", "").strip()
|
||||||
|
if not rawValue:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
fps = int(rawValue)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
_WriteHeadlessTrace("Invalid M2_RENDER_FPS=%s" % rawValue)
|
||||||
|
return
|
||||||
|
|
||||||
|
app.SetFPS(fps)
|
||||||
|
_WriteHeadlessTrace("Render FPS override=%d" % fps)
|
||||||
|
|
||||||
|
|
||||||
|
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():
|
def RunApp():
|
||||||
musicInfo.LoadLastPlayFieldMusic()
|
musicInfo.LoadLastPlayFieldMusic()
|
||||||
|
|
||||||
@@ -36,6 +98,7 @@ def RunApp():
|
|||||||
return
|
return
|
||||||
|
|
||||||
app.SetCamera(1500.0, 30.0, 0.0, 180.0)
|
app.SetCamera(1500.0, 30.0, 0.0, 180.0)
|
||||||
|
_ApplyRenderFPSOverride()
|
||||||
|
|
||||||
#Gets and sets the floating-point control word
|
#Gets and sets the floating-point control word
|
||||||
#app.SetControlFP()
|
#app.SetControlFP()
|
||||||
@@ -47,8 +110,7 @@ def RunApp():
|
|||||||
mainStream.Create()
|
mainStream.Create()
|
||||||
|
|
||||||
#mainStream.SetLoadingPhase()
|
#mainStream.SetLoadingPhase()
|
||||||
|
_SetInitialPhase(mainStream)
|
||||||
mainStream.SetLoginPhase()
|
|
||||||
#mainStream.SetSelectCharacterPhase()
|
#mainStream.SetSelectCharacterPhase()
|
||||||
#mainStream.SetCreateCharacterPhase()
|
#mainStream.SetCreateCharacterPhase()
|
||||||
#mainStream.SetSelectEmpirePhase()
|
#mainStream.SetSelectEmpirePhase()
|
||||||
@@ -58,4 +120,3 @@ def RunApp():
|
|||||||
mainStream.Destroy()
|
mainStream.Destroy()
|
||||||
|
|
||||||
RunApp()
|
RunApp()
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class PlayerGauge(ui.Gauge):
|
|||||||
self.SetPosition(-100, -100)
|
self.SetPosition(-100, -100)
|
||||||
ui.Gauge.Hide(self)
|
ui.Gauge.Hide(self)
|
||||||
|
|
||||||
def OnUpdate(self):
|
def __UpdateScreenPosition(self):
|
||||||
playerIndex = player.GetMainCharacterIndex()
|
playerIndex = player.GetMainCharacterIndex()
|
||||||
|
|
||||||
(x, y, z)=textTail.GetPosition(playerIndex)
|
(x, y, z)=textTail.GetPosition(playerIndex)
|
||||||
@@ -30,6 +30,14 @@ class PlayerGauge(ui.Gauge):
|
|||||||
isChat = textTail.IsChat(playerIndex)
|
isChat = textTail.IsChat(playerIndex)
|
||||||
ui.Gauge.SetPosition(self, int(x - self.GetWidth() // 2), int(y + 5) + isChat * 17)
|
ui.Gauge.SetPosition(self, int(x - self.GetWidth() // 2), int(y + 5) + isChat * 17)
|
||||||
|
|
||||||
|
def OnUpdate(self):
|
||||||
|
self.__UpdateScreenPosition()
|
||||||
|
|
||||||
|
def OnRender(self):
|
||||||
|
# Refresh the anchor every render so the gauge tracks interpolated
|
||||||
|
# character/text-tail positions on high refresh displays.
|
||||||
|
self.__UpdateScreenPosition()
|
||||||
|
|
||||||
def RefreshGauge(self):
|
def RefreshGauge(self):
|
||||||
|
|
||||||
self.curHP = player.GetStatus(player.HP)
|
self.curHP = player.GetStatus(player.HP)
|
||||||
|
|||||||
@@ -95,23 +95,31 @@ class PrivateShopAdvertisementBoard(ui.ThinBoard):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def OnUpdate(self):
|
def __UpdateProjectedPosition(self):
|
||||||
if not self.vid:
|
if not self.vid:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
projectVID = None
|
||||||
if systemSetting.IsShowSalesText():
|
if systemSetting.IsShowSalesText():
|
||||||
self.Show()
|
projectVID = self.vid
|
||||||
x, y = chr.GetProjectPosition(self.vid, 220)
|
elif player.GetMainCharacterIndex() == self.vid:
|
||||||
self.SetPosition(x - self.GetWidth()/2, y - self.GetHeight()/2)
|
projectVID = player.GetMainCharacterIndex()
|
||||||
|
|
||||||
else:
|
if projectVID is None:
|
||||||
for key in list(g_privateShopAdvertisementBoardDict.keys()):
|
self.Hide()
|
||||||
if player.GetMainCharacterIndex() == key: # When the private shop is visible and closed, the player's own shop ID changes.
|
return
|
||||||
g_privateShopAdvertisementBoardDict[key].Show()
|
|
||||||
x, y = chr.GetProjectPosition(player.GetMainCharacterIndex(), 220)
|
self.Show()
|
||||||
g_privateShopAdvertisementBoardDict[key].SetPosition(x - self.GetWidth()/2, y - self.GetHeight()/2)
|
x, y = chr.GetProjectPosition(projectVID, 220)
|
||||||
else:
|
self.SetPosition(x - self.GetWidth()/2, y - self.GetHeight()/2)
|
||||||
g_privateShopAdvertisementBoardDict[key].Hide()
|
|
||||||
|
def OnUpdate(self):
|
||||||
|
self.__UpdateProjectedPosition()
|
||||||
|
|
||||||
|
def OnRender(self):
|
||||||
|
# Keep the board anchored to the interpolated render position instead
|
||||||
|
# of the legacy fixed update cadence.
|
||||||
|
self.__UpdateProjectedPosition()
|
||||||
|
|
||||||
class PrivateShopBuilder(ui.ScriptWindow):
|
class PrivateShopBuilder(ui.ScriptWindow):
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ class OptionDialog(ui.ScriptWindow):
|
|||||||
self.cameraModeButtonList = []
|
self.cameraModeButtonList = []
|
||||||
self.fogModeButtonList = []
|
self.fogModeButtonList = []
|
||||||
self.tilingModeButtonList = []
|
self.tilingModeButtonList = []
|
||||||
|
self.renderFPSButtonList = []
|
||||||
|
self.renderFPSValues = [60, 120, 144, 240, 0]
|
||||||
|
self.performanceHUDButtonList = []
|
||||||
self.ctrlShadowQuality = 0
|
self.ctrlShadowQuality = 0
|
||||||
|
|
||||||
def Destroy(self):
|
def Destroy(self):
|
||||||
@@ -72,6 +75,13 @@ class OptionDialog(ui.ScriptWindow):
|
|||||||
self.fogModeButtonList.append(GetObject("fog_level2"))
|
self.fogModeButtonList.append(GetObject("fog_level2"))
|
||||||
self.tilingModeButtonList.append(GetObject("tiling_cpu"))
|
self.tilingModeButtonList.append(GetObject("tiling_cpu"))
|
||||||
self.tilingModeButtonList.append(GetObject("tiling_gpu"))
|
self.tilingModeButtonList.append(GetObject("tiling_gpu"))
|
||||||
|
self.renderFPSButtonList.append(GetObject("render_fps_60"))
|
||||||
|
self.renderFPSButtonList.append(GetObject("render_fps_120"))
|
||||||
|
self.renderFPSButtonList.append(GetObject("render_fps_144"))
|
||||||
|
self.renderFPSButtonList.append(GetObject("render_fps_240"))
|
||||||
|
self.renderFPSButtonList.append(GetObject("render_fps_max"))
|
||||||
|
self.performanceHUDButtonList.append(GetObject("performance_hud_off"))
|
||||||
|
self.performanceHUDButtonList.append(GetObject("performance_hud_on"))
|
||||||
self.tilingApplyButton=GetObject("tiling_apply")
|
self.tilingApplyButton=GetObject("tiling_apply")
|
||||||
#self.ctrlShadowQuality = GetObject("shadow_bar")
|
#self.ctrlShadowQuality = GetObject("shadow_bar")
|
||||||
except:
|
except:
|
||||||
@@ -106,6 +116,13 @@ class OptionDialog(ui.ScriptWindow):
|
|||||||
|
|
||||||
self.tilingModeButtonList[0].SAFE_SetEvent(self.__OnClickTilingModeCPUButton)
|
self.tilingModeButtonList[0].SAFE_SetEvent(self.__OnClickTilingModeCPUButton)
|
||||||
self.tilingModeButtonList[1].SAFE_SetEvent(self.__OnClickTilingModeGPUButton)
|
self.tilingModeButtonList[1].SAFE_SetEvent(self.__OnClickTilingModeGPUButton)
|
||||||
|
self.renderFPSButtonList[0].SAFE_SetEvent(self.__OnClickRenderFPS60Button)
|
||||||
|
self.renderFPSButtonList[1].SAFE_SetEvent(self.__OnClickRenderFPS120Button)
|
||||||
|
self.renderFPSButtonList[2].SAFE_SetEvent(self.__OnClickRenderFPS144Button)
|
||||||
|
self.renderFPSButtonList[3].SAFE_SetEvent(self.__OnClickRenderFPS240Button)
|
||||||
|
self.renderFPSButtonList[4].SAFE_SetEvent(self.__OnClickRenderFPSMaxButton)
|
||||||
|
self.performanceHUDButtonList[0].SAFE_SetEvent(self.__OnClickPerformanceHUDOffButton)
|
||||||
|
self.performanceHUDButtonList[1].SAFE_SetEvent(self.__OnClickPerformanceHUDOnButton)
|
||||||
|
|
||||||
self.tilingApplyButton.SAFE_SetEvent(self.__OnClickTilingApplyButton)
|
self.tilingApplyButton.SAFE_SetEvent(self.__OnClickTilingApplyButton)
|
||||||
|
|
||||||
@@ -115,6 +132,7 @@ class OptionDialog(ui.ScriptWindow):
|
|||||||
self.__ClickRadioButton(self.fogModeButtonList, systemSetting.GetFogLevel())
|
self.__ClickRadioButton(self.fogModeButtonList, systemSetting.GetFogLevel())
|
||||||
# MR-14: -- END OF -- Fog update by Alaric
|
# MR-14: -- END OF -- Fog update by Alaric
|
||||||
self.__ClickRadioButton(self.cameraModeButtonList, constInfo.GET_CAMERA_MAX_DISTANCE_INDEX())
|
self.__ClickRadioButton(self.cameraModeButtonList, constInfo.GET_CAMERA_MAX_DISTANCE_INDEX())
|
||||||
|
self.RefreshRenderSettings()
|
||||||
|
|
||||||
if musicInfo.fieldMusic==musicInfo.METIN2THEMA:
|
if musicInfo.fieldMusic==musicInfo.METIN2THEMA:
|
||||||
self.selectMusicFile.SetText(uiSelectMusic.DEFAULT_THEMA)
|
self.selectMusicFile.SetText(uiSelectMusic.DEFAULT_THEMA)
|
||||||
@@ -179,6 +197,41 @@ class OptionDialog(ui.ScriptWindow):
|
|||||||
|
|
||||||
self.__ClickRadioButton(self.fogModeButtonList, index)
|
self.__ClickRadioButton(self.fogModeButtonList, index)
|
||||||
|
|
||||||
|
def __ApplyAndSaveConfig(self):
|
||||||
|
systemSetting.ApplyConfig()
|
||||||
|
systemSetting.SaveConfig()
|
||||||
|
|
||||||
|
def __GetRenderFPSButtonIndex(self):
|
||||||
|
renderFPS = systemSetting.GetRenderFPS()
|
||||||
|
if renderFPS <= 0:
|
||||||
|
return len(self.renderFPSValues) - 1
|
||||||
|
|
||||||
|
try:
|
||||||
|
return self.renderFPSValues.index(renderFPS)
|
||||||
|
except ValueError:
|
||||||
|
bestIndex = 0
|
||||||
|
bestDistance = abs(self.renderFPSValues[0] - renderFPS)
|
||||||
|
for index in xrange(len(self.renderFPSValues) - 1):
|
||||||
|
distance = abs(self.renderFPSValues[index] - renderFPS)
|
||||||
|
if distance < bestDistance:
|
||||||
|
bestIndex = index
|
||||||
|
bestDistance = distance
|
||||||
|
return bestIndex
|
||||||
|
|
||||||
|
def RefreshRenderSettings(self):
|
||||||
|
self.__ClickRadioButton(self.renderFPSButtonList, self.__GetRenderFPSButtonIndex())
|
||||||
|
self.__ClickRadioButton(self.performanceHUDButtonList, 1 if systemSetting.IsShowPerformanceHUD() else 0)
|
||||||
|
|
||||||
|
def __SetRenderFPS(self, fps):
|
||||||
|
systemSetting.SetRenderFPS(fps)
|
||||||
|
self.__ApplyAndSaveConfig()
|
||||||
|
self.RefreshRenderSettings()
|
||||||
|
|
||||||
|
def __SetPerformanceHUD(self, isVisible):
|
||||||
|
systemSetting.SetShowPerformanceHUDFlag(1 if isVisible else 0)
|
||||||
|
self.__ApplyAndSaveConfig()
|
||||||
|
self.RefreshRenderSettings()
|
||||||
|
|
||||||
def __OnClickCameraModeShortButton(self):
|
def __OnClickCameraModeShortButton(self):
|
||||||
self.__SetCameraMode(0)
|
self.__SetCameraMode(0)
|
||||||
|
|
||||||
@@ -194,6 +247,27 @@ class OptionDialog(ui.ScriptWindow):
|
|||||||
def __OnClickFogModeLevel2Button(self):
|
def __OnClickFogModeLevel2Button(self):
|
||||||
self.__SetFogLevel(2)
|
self.__SetFogLevel(2)
|
||||||
|
|
||||||
|
def __OnClickRenderFPS60Button(self):
|
||||||
|
self.__SetRenderFPS(60)
|
||||||
|
|
||||||
|
def __OnClickRenderFPS120Button(self):
|
||||||
|
self.__SetRenderFPS(120)
|
||||||
|
|
||||||
|
def __OnClickRenderFPS144Button(self):
|
||||||
|
self.__SetRenderFPS(144)
|
||||||
|
|
||||||
|
def __OnClickRenderFPS240Button(self):
|
||||||
|
self.__SetRenderFPS(240)
|
||||||
|
|
||||||
|
def __OnClickRenderFPSMaxButton(self):
|
||||||
|
self.__SetRenderFPS(0)
|
||||||
|
|
||||||
|
def __OnClickPerformanceHUDOffButton(self):
|
||||||
|
self.__SetPerformanceHUD(False)
|
||||||
|
|
||||||
|
def __OnClickPerformanceHUDOnButton(self):
|
||||||
|
self.__SetPerformanceHUD(True)
|
||||||
|
|
||||||
def __OnChangeMusic(self, fileName):
|
def __OnChangeMusic(self, fileName):
|
||||||
self.selectMusicFile.SetText(fileName[:MUSIC_FILENAME_MAX_LEN])
|
self.selectMusicFile.SetText(fileName[:MUSIC_FILENAME_MAX_LEN])
|
||||||
|
|
||||||
@@ -239,6 +313,8 @@ class OptionDialog(ui.ScriptWindow):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def Show(self):
|
def Show(self):
|
||||||
|
self.RefreshRenderSettings()
|
||||||
|
self.__SetCurTilingMode()
|
||||||
ui.ScriptWindow.Show(self)
|
ui.ScriptWindow.Show(self)
|
||||||
|
|
||||||
def Close(self):
|
def Close(self):
|
||||||
|
|||||||
BIN
assets/sound2/sound/monster2/outlaw/fall.wav
Normal file
BIN
assets/sound2/sound/monster2/outlaw/fall.wav
Normal file
Binary file not shown.
BIN
assets/sound2/sound/pc2/assassin/bow/attack1.wav
Normal file
BIN
assets/sound2/sound/pc2/assassin/bow/attack1.wav
Normal file
Binary file not shown.
@@ -1,5 +1,5 @@
|
|||||||
ScriptType CharacterSoundInformation
|
ScriptType CharacterSoundInformation
|
||||||
|
|
||||||
SoundDataCount 2
|
SoundDataCount 2
|
||||||
SoundData00 0.066000 "sound/pc2/assassin/dualhand_sword/combo7.wav"
|
SoundData00 0.231000 "sound/pc2/assassin/dualhand_sword/combo4.wav"
|
||||||
SoundData01 0.033000 "sound/common/swing/w_1h_c_2.wav"
|
SoundData01 0.198000 "sound/common/swing/a_dh_c_4.wav"
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
import uiScriptLocale
|
import uiScriptLocale
|
||||||
|
|
||||||
ROOT_PATH = "d:/ymir work/ui/public/"
|
ROOT_PATH = "d:/ymir work/ui/public/"
|
||||||
|
OPTION_RENDER_FPS = getattr(uiScriptLocale, "OPTION_RENDER_FPS", "Render FPS")
|
||||||
|
OPTION_RENDER_FPS_MAX = getattr(uiScriptLocale, "OPTION_RENDER_FPS_MAX", "MAX")
|
||||||
|
OPTION_PERFORMANCE_HUD = getattr(uiScriptLocale, "OPTION_PERFORMANCE_HUD", "Perf HUD")
|
||||||
|
OPTION_ON = getattr(uiScriptLocale, "OPTION_ON", "On")
|
||||||
|
OPTION_OFF = getattr(uiScriptLocale, "OPTION_OFF", "Off")
|
||||||
|
|
||||||
TEMPORARY_X = +13
|
TEMPORARY_X = +13
|
||||||
TEXT_TEMPORARY_X = -10
|
TEXT_TEMPORARY_X = -10
|
||||||
@@ -15,7 +20,7 @@ window = {
|
|||||||
"y" : 0,
|
"y" : 0,
|
||||||
|
|
||||||
"width" : 305,
|
"width" : 305,
|
||||||
"height" : 255,
|
"height" : 295,
|
||||||
|
|
||||||
"children" :
|
"children" :
|
||||||
(
|
(
|
||||||
@@ -27,7 +32,7 @@ window = {
|
|||||||
"y" : 0,
|
"y" : 0,
|
||||||
|
|
||||||
"width" : 305,
|
"width" : 305,
|
||||||
"height" : 255,
|
"height" : 295,
|
||||||
|
|
||||||
"children" :
|
"children" :
|
||||||
(
|
(
|
||||||
@@ -261,6 +266,124 @@ window = {
|
|||||||
"down_image" : ROOT_PATH + "middle_Button_03.sub",
|
"down_image" : ROOT_PATH + "middle_Button_03.sub",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name" : "render_fps_mode",
|
||||||
|
"type" : "text",
|
||||||
|
|
||||||
|
"x" : 18,
|
||||||
|
"y" : 210 + 2,
|
||||||
|
|
||||||
|
"text" : OPTION_RENDER_FPS,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name" : "render_fps_60",
|
||||||
|
"type" : "radio_button",
|
||||||
|
|
||||||
|
"x" : 82,
|
||||||
|
"y" : 210,
|
||||||
|
|
||||||
|
"text" : "60",
|
||||||
|
|
||||||
|
"default_image" : ROOT_PATH + "small_Button_01.sub",
|
||||||
|
"over_image" : ROOT_PATH + "small_Button_02.sub",
|
||||||
|
"down_image" : ROOT_PATH + "small_Button_03.sub",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name" : "render_fps_120",
|
||||||
|
"type" : "radio_button",
|
||||||
|
|
||||||
|
"x" : 124,
|
||||||
|
"y" : 210,
|
||||||
|
|
||||||
|
"text" : "120",
|
||||||
|
|
||||||
|
"default_image" : ROOT_PATH + "small_Button_01.sub",
|
||||||
|
"over_image" : ROOT_PATH + "small_Button_02.sub",
|
||||||
|
"down_image" : ROOT_PATH + "small_Button_03.sub",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name" : "render_fps_144",
|
||||||
|
"type" : "radio_button",
|
||||||
|
|
||||||
|
"x" : 166,
|
||||||
|
"y" : 210,
|
||||||
|
|
||||||
|
"text" : "144",
|
||||||
|
|
||||||
|
"default_image" : ROOT_PATH + "small_Button_01.sub",
|
||||||
|
"over_image" : ROOT_PATH + "small_Button_02.sub",
|
||||||
|
"down_image" : ROOT_PATH + "small_Button_03.sub",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name" : "render_fps_240",
|
||||||
|
"type" : "radio_button",
|
||||||
|
|
||||||
|
"x" : 208,
|
||||||
|
"y" : 210,
|
||||||
|
|
||||||
|
"text" : "240",
|
||||||
|
|
||||||
|
"default_image" : ROOT_PATH + "small_Button_01.sub",
|
||||||
|
"over_image" : ROOT_PATH + "small_Button_02.sub",
|
||||||
|
"down_image" : ROOT_PATH + "small_Button_03.sub",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name" : "render_fps_max",
|
||||||
|
"type" : "radio_button",
|
||||||
|
|
||||||
|
"x" : 250,
|
||||||
|
"y" : 210,
|
||||||
|
|
||||||
|
"text" : OPTION_RENDER_FPS_MAX,
|
||||||
|
|
||||||
|
"default_image" : ROOT_PATH + "small_Button_01.sub",
|
||||||
|
"over_image" : ROOT_PATH + "small_Button_02.sub",
|
||||||
|
"down_image" : ROOT_PATH + "small_Button_03.sub",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name" : "performance_hud_mode",
|
||||||
|
"type" : "text",
|
||||||
|
|
||||||
|
"x" : 18,
|
||||||
|
"y" : 235 + 2,
|
||||||
|
|
||||||
|
"text" : OPTION_PERFORMANCE_HUD,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name" : "performance_hud_off",
|
||||||
|
"type" : "radio_button",
|
||||||
|
|
||||||
|
"x" : 110,
|
||||||
|
"y" : 235,
|
||||||
|
|
||||||
|
"text" : OPTION_OFF,
|
||||||
|
|
||||||
|
"default_image" : ROOT_PATH + "small_Button_01.sub",
|
||||||
|
"over_image" : ROOT_PATH + "small_Button_02.sub",
|
||||||
|
"down_image" : ROOT_PATH + "small_Button_03.sub",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name" : "performance_hud_on",
|
||||||
|
"type" : "radio_button",
|
||||||
|
|
||||||
|
"x" : 160,
|
||||||
|
"y" : 235,
|
||||||
|
|
||||||
|
"text" : OPTION_ON,
|
||||||
|
|
||||||
|
"default_image" : ROOT_PATH + "small_Button_01.sub",
|
||||||
|
"over_image" : ROOT_PATH + "small_Button_02.sub",
|
||||||
|
"down_image" : ROOT_PATH + "small_Button_03.sub",
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
## 그림자
|
## 그림자
|
||||||
# {
|
# {
|
||||||
|
|||||||
@@ -163,23 +163,14 @@ 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:
|
1. On a trusted machine (not random laptop), with the private signing key present:
|
||||||
```bash
|
```bash
|
||||||
./scripts/make-release.sh --source /path/to/fresh/client --version 2026.04.14-1 \
|
./scripts/make-release.sh --version 2026.04.14-1 --source /path/to/fresh/client
|
||||||
--previous 2026.04.13-3 --notes notes.md --dry-run
|
|
||||||
```
|
```
|
||||||
[`scripts/make-release.sh`](../scripts/make-release.sh) is the single entry
|
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).
|
||||||
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.
|
3. Human review: diff the new manifest against the previous one, sanity-check size and file count.
|
||||||
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.
|
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/
|
||||||
|
```
|
||||||
5. Verify from a second machine: `curl` the manifest, check signature, check a random blob.
|
5. Verify from a second machine: `curl` the manifest, check signature, check a random blob.
|
||||||
6. Tag the release in git.
|
6. Tag the release in git.
|
||||||
|
|
||||||
|
|||||||
@@ -1,169 +0,0 @@
|
|||||||
#!/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