Skip to content

Commit 000340d

Browse files
committed
Feature: Add new example code
1 parent 684d752 commit 000340d

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed

ExampleModCode.cs

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using NeoModLoader.api.attributes;
77
using NeoModLoader.General;
88
using UnityEngine;
9+
910
namespace ExampleMod;
1011

1112
/// <summary>
@@ -32,9 +33,11 @@ public class ExampleModMain : BasicMod<ExampleModMain>, IReloadable, IUnloadable
3233
// Just for displaying mod reloading effect. To emulate the effect of reloading mod, you can replace _reload_switch with manual modifying.
3334
// 仅用于展示显示模组重载效果(因为代码是静态的, 不能自动修改), 你可以将 _reload_switch 替换为手动修改
3435
internal static bool _reload_switch;
36+
3537
// It is used for storing self made prefab, avoiding prefab objects under root scene. It's optional.
3638
// 用于存储自制的预制体, 避免预制体对象直接暴露在场景根节点下. 不是必需的.
3739
internal static Transform prefab_library;
40+
3841
/// <summary>
3942
/// <para>
4043
/// To test reloading function, you can modify traits in <see cref="ExampleTraits" /> or trait action in
@@ -71,6 +74,7 @@ public void Reload()
7174
LM.LoadLocales(file);
7275
}
7376
}
77+
7478
LM.ApplyLocale();
7579
// Reload mod resources when mod reloaded, it's optional.
7680
// 重载模组时重新加载模组资源, 不是必需的
@@ -150,6 +154,7 @@ protected override void OnModLoad()
150154
{
151155
Config.isEditor = true;
152156
}
157+
153158
// Example of add name generators and example of mod optional dependencies.
154159
// 添加名字生成器的示例和模组可选依赖的示例.
155160
ExampleNameGenerators.init();
@@ -168,6 +173,7 @@ protected override void OnModLoad()
168173
// 创建事件处理器和添加新的世界日志消息的示例.
169174
// 它实现了两个事件处理器来处理plot开始事件和世界日志消息格式事件, 以添加新的世界日志消息类型来提示一场plot的开始.
170175
ExampleEventHandlers.init();
176+
ExampleActorOverrideSprite.init();
171177
}
172178

173179
// Example code for mod be called by other mods. You can test mod dependencies by calling this method in your mod. If no other mods call this method, this method is simply useless.

content/ExampleActorOverrideSprite.cs

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
using System.Linq;
2+
using System.Text;
3+
using UnityEngine;
4+
5+
namespace ExampleMod.Content;
6+
7+
internal static class ExampleActorOverrideSprite
8+
{
9+
private static readonly string[] walk_sprites =
10+
{
11+
"actors/races/human/unit_male_1/walk_0", "actors/races/human/unit_male_1/walk_1",
12+
"actors/races/human/unit_male_1/walk_2", "actors/races/human/unit_male_1/walk_3"
13+
};
14+
15+
private static readonly string[] swim_sprites =
16+
{
17+
"actors/races/human/unit_male_2/swim_0", "actors/races/human/unit_male_2/swim_1",
18+
"actors/races/human/unit_male_2/swim_2", "actors/races/human/unit_male_2/swim_3"
19+
};
20+
21+
private static readonly string[] idle_sprites =
22+
{
23+
"actors/races/human/unit_male_1/walk_3"
24+
};
25+
26+
private static readonly string[] attack_sprites =
27+
{
28+
"actors/t_sheep/walk_0", "actors/t_sheep/walk_1"
29+
};
30+
31+
public static void init()
32+
{
33+
ActorAsset asset = AssetManager.actor_library.get(SA.unit_human);
34+
asset.has_override_sprite = true;
35+
asset.get_override_sprite = get_human_override_sprite;
36+
}
37+
38+
private static Sprite get_human_override_sprite(Actor actor)
39+
{
40+
actor.data.get("last_anim_frame_idx", out int last_frame);
41+
actor.data.get("last_anim_state", out string last_anim_state);
42+
var frame_path = idle_sprites[0];
43+
var curr_frame = last_frame + 1;
44+
var curr_anim_state = last_anim_state;
45+
46+
// Check attack at first
47+
if (Mathf.Abs(actor.attackTimer - actor.s_attackSpeed_seconds) < 0.01f)
48+
{
49+
// Just begin attack action
50+
curr_frame = 0;
51+
curr_anim_state = "attack";
52+
}
53+
54+
if (actor.attackTimer > 0 && curr_anim_state == "attack")
55+
{
56+
// Continue play the attack animation
57+
if (curr_frame >= attack_sprites.Length)
58+
{
59+
// attack animation finishes. Turn to idle
60+
// do nothing, it can be done below
61+
}
62+
else
63+
{
64+
frame_path = attack_sprites[curr_frame];
65+
66+
actor.data.set("last_anim_frame_idx", curr_frame);
67+
actor.data.set("last_anim_state", curr_anim_state);
68+
return get_single_sprite(frame_path);
69+
}
70+
}
71+
72+
if (actor.isAffectedByLiquid())
73+
curr_anim_state = "swim";
74+
else if (actor.is_moving)
75+
curr_anim_state = "walk";
76+
else
77+
curr_anim_state = "idle";
78+
79+
switch (curr_anim_state)
80+
{
81+
case "walk":
82+
curr_frame %= walk_sprites.Length;
83+
frame_path = walk_sprites[curr_frame];
84+
break;
85+
case "swim":
86+
curr_frame %= swim_sprites.Length;
87+
frame_path = swim_sprites[curr_frame];
88+
break;
89+
case "idle":
90+
curr_frame %= idle_sprites.Length;
91+
frame_path = idle_sprites[curr_frame];
92+
break;
93+
}
94+
95+
actor.data.set("last_anim_frame_idx", curr_frame);
96+
actor.data.set("last_anim_state", curr_anim_state);
97+
return get_single_sprite(frame_path);
98+
}
99+
100+
private static Sprite get_single_sprite(string path)
101+
{
102+
var components = path.Split('/');
103+
104+
var folder_builder = new StringBuilder();
105+
folder_builder.Append(components[0]);
106+
for (var i = 1; i < components.Length - 1; i++)
107+
{
108+
folder_builder.Append('/');
109+
folder_builder.Append(components[i]);
110+
}
111+
112+
var sprite_list = SpriteTextureLoader.getSpriteList(folder_builder.ToString());
113+
return sprite_list.FirstOrDefault(x => x.name == components.Last());
114+
}
115+
}

0 commit comments

Comments
 (0)