This is a FAQ page about creating plug-ins using C#.
The content of this FAQ is based on the inquiries we have received from our users and the responses we have received from our development team.
Please refer to the How to Use Plug-ins section.
You can use a different editor by specifying an association for the sln file other than Visual Studio.
"Conversation" can be achieved with the following method. The position of the window (top, middle, bottom) changes when the 0's are set to 1, 2, 3, etc.
mapScene.ShowDialogue(msg, 0, MenuControllerBase.WindowTypes.DIALOGUE, new AbstractRenderObject.GameContent.DialogueCharacterProperty() new AbstractRenderObject.GameContent.DialogueCharacterProperty(), mapChr.guId);
The DialogueCharacterProperty() parameter can be used to assign a graphic of the speaking cast, but the parameters are generally linked to what can be specified in the panel.
"Message" is the following method. As with conversation, the second parameter, 0, specifies the window position.
mapScene.ShowMessage(stringAttr.value, 0, MenuControllerBase.WindowTypes.MESSAGE, mapChr.guId);
In addition, the "ticker" will be the following method.
mapScene.ShowTelop(msg, 0, MenuControllerBase.WindowTypes.TELOP, new AbstractRenderObject.GameContent.TelopProperty(), mapChr.guId);
ShowDialogue and ShowMessage return an ad hoc id in the return value, so you can use this to execute
mapScene.IsQueuedDialogue(id)
and
mapScene.IsQueuedMessage(id)
to see if the displayed conversation or message is still being displayed (not closed).
This is not possible at the Ver. 1.9 stage.
You can use
Graphics.DrawString (with borders)
or
Graphics.DrawStringSoloColor (without borders).
At this time (ver. 1.9), we do not release methods for text decoration by formatting.
(If you need formatted text decoration, please wait for the release of SpriteManager.)
Please use the following:
var render = catalog.getItemFromName<Yukar.Common.Rom.RenderSettings>("Rendering Setting Name"); mapScene.mapDrawer.setRenderSettings(render);
Please use one of the following two options.
mapChr.playMotion("MotionName") mapScene.hero.playMotion(("MotionName", 0.2f, true, lockMotion))
lockMotion = Whether to prevent disarming by walking, etc. / locked by true, false for no locking.
To assign a key and apply it, please use the following.
mapScene.hero.getModelInstance().setMorphBlend("KeyName", 0.5f);
To assign a clip and apply it, please use the following.
The parameters are the target, the clip name, the interpolation time, and whether to reset other blendshapes.
ScriptRunner.AddBlendShapeTask(mapScene.hero, "ClipName", 4, false);
Please use the sample code by binding it to an event.
MotionUtil.cs
GetMotionLoopCount to obtain the number of motion loops.
In the case of a one-shot, the motion can be considered complete if it is 1.
PlayMotionImmediately starts motion playback without blending.
Use this when the normal motion playback panel is too much of a distraction from the blending.
It can be obtained in the following way:
// Find the common event by name (if you know the GUID, you can set the GUID directly) var guid = catalog.getGameSettings().commonEvents.FirstOrDefault(x => catalog.getItemFromGuid(x)?.name == "Name_of_Event_to_be_Executed"); if(guid != Guid.Empty) { // Obtain runner from map scene var runner = mapScene.GetScriptRunner(guid); // If a runner could not be obtained (not a single sheet meeting the conditions), then escape. if (runner == null) return; // Start execution bool result = runner.Run(); // If you want to run it during a battle, flag it to be included in the main loop of the battle process. var btlEvtCtl = mapScene as BattleEventControllerBase; if (result && btlEvtCtl != null) { btlEvtCtl.start(guid); } }
By passing Func<bool> to SetWaiter as shown below, the event progress can be stopped until func returns false.
[BakinFunction] public void WaitFunc() { float elapsed = 0; runner.SetWaiter(() => { elapsed += GameMain.getElapsedTime(); return elapsed < 10; // Stop the progress of the event until 10 seconds have elapsed. }); }
Please call the following for each frame.
mapScene.GetCharacterScreenPos(MapCharacter, out var x, out var y, MapScene.EffectPosType.Head); mapScene.menuWindow.AdjustBalloonRect(x, y - 32);
color should be assigned the Microsoft.Xna.Framework.Color class.
As for font, if you do not need to specify the size, assign fontId=0 to the following method of the Graphics class instead of the TextDrawer class.
Graphics.DrawString(0, "String_to_be_Displayed", new Vector2(0, 0), Color.White);
If you need to assign a size, please create an instance of the SharpKmyGfx.Font class and use the methods of TextDrawer.
Note that the created instance of the SharpKmyGfx class must be discarded by your own process.
The following will be the way:
// Display image int spIndex = 0; // Image Number int sliceNo = 0; // If the image has a slice assigned to it, the top-left corner is 0 (horizontal priority) and what number of slice should be displayed. var guid = catalog.getItemFromName<Yukar.Common.Resource.Texture>("Texture_Name")?.guId ?? Guid.Empty; mapScene.spManager.ShowPicture(spIndex, guid, 100, 100, Microsoft.Xna.Framework.Color.White, sliceNo); // Set the coordinates int x = 0; // Coordinate X int y = 0; // Coordinate Y mapScene.spManager.Move(spIndex, 0, x, y); // Display string as an image int spIndex = 0; // Image Number int x = 0; // Coordinate X int y = 0; // Coordinate Y mapScene.spManager.ShowText(spIndex, "String_to_be_Displayed", x, y);
Each of them is as follows:
mapScene.playerLocked &= ~MapScene.PLAYER_LOCK_BY_EVENT;
mapScene.playerLocked |= MapScene.PLAYER_LOCK_BY_EVENT;
mapScene.owner.data.start.fixDirectionPlayer = true; mapScene.hero.dirMethod = MapCharacter.DirectionMethods.FIX;
mapScene.owner.data.start.fixDirectionPlayer = false; mapScene.hero.dirMethod = MapCharacter.DirectionMethods.NORMAL;
mapScene.owner.data.system.dashAvailable = true;
mapScene.owner.data.system.dashAvailable = false;
mapScene.owner.data.system.jumpAvailable = true;
mapScene.owner.data.system.jumpAvailable = false;
mapScene.owner.data.system.walkAvailable = true;
mapScene.owner.data.system.walkAvailable = true;
It is not disclosed as a function.
For those with rigid bodies, the physics is handled by specifying the following.
(tgt is an instance of the MapCharacter class)
var rgd = tgt.getRigidbody(); tgt.setGravity(speed); tgt.fixHeight = false; tgt.refreshRigidBodyMask(); rgd.activate(true); rgd.setAngularDamping(0.5f); rgd.setPositionDamping(0.5f);
For those without a rigid body, please move the Y position by self.
Please measure the time using the following:
[BakinFunction] public void WaitFunc() { float elapsed = 0; runner.SetWaiter(() => { elapsed += GameMain.getElapsedTime(); return elapsed < 10; // Stop the progress of the event until 10 seconds have elapsed. }); }
MapScene.GetCharacterScreenPos() is used for both panels to convert to screen coordinates as well.
The currently displayed free layouts are stored in GameMain.instance.freeLayouts.
If you want to display something new that is not already displayed, you need to find a layout ROM from catalog as shown below.
// When open var lyt = catalog.getLayoutProperties().AllLayoutNodes.FirstOrDefault(x => x.Name == "ItemSelect"); if (lyt != null) { GameMain.instance.ShowFreeLayout(lyt.Guid); }
There is no method that explicitly determines the Collision Detection.
For collision detection at the time of contact, use mapChr.collisionStatus.hitChrList, which contains a list of hit targets, or use raycasting.
The following is the code:
mapChr.collisionStatus.playerCollidable = true; // Collide with Player mapChr.collisionStatus.eventCollidable = true; // Collide with Other Events mapChr.fixPos = true; // Move When Push
The following call is required for the above specified changes:
mapChr.refreshRigidBodyMask(); // If only collidable is changed mapChr.refreshRigidBody(); // If fixPos is also changed
MAP_SLOPE targets slopes and stairs.
This is done with "Check Surrounding Collision Detection (Raycast)", but if the check destination is specified as "Terrain", it will hit the slope.
(CollisionType.MAP and CollisionType.MAP_SLOPE are targeted in "Terrain.")
However, it is not applicable in cases where the height of the slope is low.
Try adjusting the height of the raycast.
You can do this in the following way:
var result = chr.getRigidbody().getPhysicsBase().rayCast( Util.ToKmyVector(thisCastPos), // from Util.ToKmyVector(playerPos), // to (ushort)(CollisionType.PLAYER) , hit);
Please use AdvancedEnhance().
Please refer to the script below for instructions on how to use it.
ItemEnhancementSampleScript_1.cs
The following steps can be taken to obtain enhanced items with event execution.
[BakinFunction]
public void AddEnhancedItem() { var item = catalog.getItemFromName<Yukar.Common.Rom.NItem>("Longsword"); var enhancedItem = item.CreateEnhancedItem(); catalog.addEnhancedItem(enhancedItem); GameMain.instance.data.party.SetItemNum(enhancedItem.guId, 1, true); var ev = catalog.getItemFromGuid(item.scriptOnNew) as Yukar.Common.Rom.Event; var runner = mapScene.mapEngine.AddEvent(mapScene, ev, enhancedItem); }
This can be done by using the following:
var item = catalog.getItemFromName<Yukar.Common.Rom.NItem>("Longsword"); var enhancedItemList = GameMain.instance.data.party.Items.Where(x => x.BaseItemId == item.guId).Select(x => x.enhancedItem).ToList();
It is possible if you can find the cast from catalog and pass its eventRef.
Basically, you can find what you are defining in the Database from catalog.
GameMain.instance.pushTask(() => { var cast = catalog.getItemFromName<Yukar.Common.Rom.Cast>("Name_of_Cast_Member_You_Wish_to_Find"); targetEvent.CreateEvent(cast.eventRef, targetEvent.getDirectionRadian()); return false; });
Please use the following:
// Map events are currently controlled from the system only by HP, which can be accessed in the following way mapChr.battleStatus.HitPoint; // Not accessed by the map battle system, but to access other consumption statuses mapChr.battleStatus.battleStatusData.consumptionStatusValue.GetStatus(catalog.getGameSettings(), "Status_Key"); // For obtaining other normal statuses mapChr.battleStatus.battleStatusData.statusValue.GetStatus(catalog.getGameSettings(), "Status_Key");
name is the motion name and blendTime is the motion's blend start time.
Assigning false by isTemporary will change the name of the motion that is currently playing.
This motion name is used to determine the behavior if the motion name is walk/run/jumpup/landing, etc. If set to true, this motion name is not changed.
The doMotionLock is a flag that prevents motion changes caused by user operation until the motion has completed one cycle, but it should be considered only as a good luck charm.
After the = in the parameter portion of the definition (e.g., =false) is the value that will be used if the parameter is omitted.
void Yukar.Engine.MapCharacter.playMotion( string name, float blendTime = 0.2f, bool isTemporary = false, bool doLockMotion = false )
Please refer to the following script to obtain from the common event. (Only functions are described.)
Talkable.txt
To obtain from a normal event, change the method as follows.
[BakinFunction(Description = "The player can talk to this event = 1 / Cannot talk = 0")] public int GetTalkableForThis() { // Obtain the currently selected sheet var scriptGuid = mapChr.getCurrentSheet()?.script ?? Guid.Empty; var script = catalog.getItemFromGuid(scriptGuid) as Yukar.Common.Rom.Script; // No sheet with conditions satisfied if (script == null) return 0; // Even if it's a talkable event, if it's empty inside, ignore it. if (script.commands.Count == 0) return 0; // If it is in a talkable position, return 1. if (mapScene.hero.collisionStatus.talkableChrList.Contains(mapChr) && script.trigger == Yukar.Common.Rom.Script.Trigger.TALK) return 1; return 0; }
This is not possible at this time (Ver. 1.10).
Please use the following.
mapChr.SetSubGraphicOpacity
Subgraphic positions are interpreted in mapChr.DisplayObjects as a matrix get function for updating the coordinates of each display object, so they cannot be changed dynamically.
It can be obtained using the following.
((Yukar.Common.Resource.GfxResourceBase)mapChr.getGraphic()).SubGraphics[SubgraphicNumber].useTranslateOnly
Changes are not recommended, as they will directly rewrite the resource.
The following pos, rot, and scale manage these information.
((Yukar.Common.Resource.GfxResourceBase)mapChr.getGraphic()).SubGraphics[SubgraphicNumber]
Changes are not recommended, as they will directly rewrite the resource.
The following useLight manages the on/off information.
((Yukar.Common.Resource.GfxResourceBase)mapChr.getGraphic()).SubGraphics[SubgraphicNumber]
Changes are not recommended, as they will directly rewrite the resource.
This can be done by the following way.
var spIndex = 10; // Sprite Number var guid = new Guid("c15f94b6-d4a0-46c4-bc43-2db2f64471ac"); // GUID for slice animation var zoom = 100; var x = 640; var y = 360; mapScene.spManager.ShowPicture(spIndex, guid, zoom, zoom, Microsoft.Xna.Framework.Color.White, new Yukar.Common.Rom.Script.StringAttr("walk"), x, y);
The GUID of the slice animation can be obtained by right-clicking on the Resources screen > Copy GUID.
Unlike Graphics.drawImage, this can be executed only once and will continue to be displayed thereafter.
It can be moved with "mapScene.spManager.Move" and removed with "mapScene.spManager.Hide".
This is the class used in the "Display Image" event panel.
The following procedure can be used to set up the settings.
var index = 1; // Target subgraphic number foreach (var obj in mapChr.DisplayObjects) { if(obj.index == index && obj.instance is SharpKmyGfx.LocalLight lgt) { lgt.setIntensity(Intensity); lgt.setColor(Color); lgt.setRadius(Radius); } }
Changes are not recommended, as they will directly rewrite the resource.
This feature is not available in the engine because it uses an editor-specific rendering path (pickup buffer).
Please use the following.
mapScene.map.mapCameraRange
if(mapScene.map.mapCameraRange == Rectangle.Empty) is true, it is unset (unrestricted).
Set the model GUID in
mapScene.mapDrawer.renderSettings.skyModel
and then after setting the environment map texture GUID in
mapScene.mapDrawer.renderSettings.reflection
execute
mapScene.mapDrawer.setRenderSettings(mapScene.mapDrawer.renderSettings);
You can change it with the following code.
var lgt = mapScene.mapDrawer.mapRom.localLights.FirstOrDefault(x => x.name == "Name_of_the_Local_Light_You_Want_to_Find");
lgt.setIntensity(Intensity); lgt.setColor(Color); lgt.setRadius(Radius);
It can be obtained from mapScene.mapDrawer.renderSettings.
Regarding the settings, some options are reflected by changing the value of this setting, while others are not immediately reflected.
To change the elements that require loading of resources such as skyboxes, use mapScene.mapDrawer.setRenderSettings().
The following code can be used to obtain the cast type of mapChr.
var type = mapChr.rom?.CastType ?? Yukar.Common.Rom.CastType.ALLY;
Refer Collision Detection between Cast Members and Events to make a determination.
It is possible with the following code.
var viewer = mapScene.fieldBattleViewer; viewer.zoomedScale = 2.0f; // Scale at just the right time to come out viewer.damageScale = 1.0f; // Eventual scale viewer.zoomTime = 0.1f; // Time to reach eventual scale viewer.drawTime = 1.0f; // Time until damage disappears viewer.damageColor = Microsoft.Xna.Framework.Color.White; // Damage color viewer.criticalDamageColor = Microsoft.Xna.Framework.Color.Red; // Critical damage color viewer.criticalDamageColor = Microsoft.Xna.Framework.Color.Red; // Critical damage color
You can also create your own damage rendering process using the attached script.
ChangeFieldBattleViewer.cs
Since the judgment is made randomly based on the critical rate, it cannot simply be determined to occur.
It would be a good idea to use state changes to temporarily increase or decrease the critical rate.
You can still obtain the information by using the following.
mapChr.rom.InvincibleTime
However, the change is not recommended because it would directly modify the Database.
There is a definition in MapCharacter.invalidDamageColor.
You can switch using the following.
GameMain.instance.data.start.controlMode = Yukar.Common.Rom.GameSettings.ControlMode.NORMAL; GameMain.instance.data.start.controlMode = Yukar.Common.Rom.GameSettings.ControlMode.RESIDENT_EVIL_LIKE;
The scale itself can be obtained with GameMain.instance.catalog.getGameSettings().TalkColliderScale.
However, changes are not recommended since they directly edit the value of the Game Definition.
It is not recommended to change the values for GameSettings in general, as any changes will be retained even after the test play is completed.
It can be obtained and changed using the following.
mapScene.mapFixCamera
In addition, individual enable/disable for each camera operation can be obtained and changed by using the following.
owner.data.start.camLockX owner.data.start.camLockY owner.data.start.camLockZoom owner.data.start.camLockReset
You can use the following to obtain the states of each.
catalog.getGameSettings().CameraAvoidObjects catalog.getGameSettings().CameraAvoidTerrain
However, changes are not recommended since they directly edit the value of the Game Definition.
It is possible to obtain information using the following.
GameMain.instance.catalog.getGameSettings().isTpsMode
However, changes are not recommended since they directly edit the value of the Game Definition.
Not possible. Please use the Game Definition settings as they are.
It is possible to obtain the speed using the following.
GameMain.instance.catalog.getGameSettings().DefaultRotateSpeed
However, changes are not recommended since they directly edit the value of the Game Definition.
Cannot be done.
Instead, create your own process to rotate the camera according to the value of Input.GetAxis() and change the rotation speed accordingly.
It is possible to obtain information using the following.
catalog.getGameSettings().meta.buildVer
The information can then be displayed on the layout by storing it in a variable as shown below.
GameMain.instance.data.system.SetVariable("VariableName", catalog.getGameSettings().meta.buildVer.ToString(), Guid.Empty, false);
However, running C# on the default title screen is not possible as of Ver 1.9.
Therefore, the title screen should be skipped in the Game Definition and used with the in-game title screen in the event.
A sample code is attached.
ConfigGetter.cs
It can be obtained by executing the C# method "GetAutoDash" after assigning it.
Please use the following.
MapCharacter.getRigidBody().setFriction(FrictionValue)
However, since MapCharacter controls friction accordingly, it may become invalid at a moment's notice.
The following method can be used.
mapChr.setOpacityMultiplier(0.5f); // Fully transparent at Transparency 0f
Regarding setOpacityMultiplier, the player is constantly monitoring and applying transparency changes due to state changes, so any changes will be overwritten.
Try setting every frame with AfterDraw().
Please use the code below.
// To open var lyt = catalog.getLayoutProperties().AllLayoutNodes.FirstOrDefault(x => x.Name == "ItemSelect"); if (lyt != null) { GameMain.instance.ShowFreeLayout(lyt.Guid); } // To close var lyt = GameMain.instance.freeLayouts.FirstOrDefault(x => x.LayoutNode.Name == "ItemSelect"); if (lyt != null) { GameMain.instance.HideFreeLayout(lyt.LayoutGuid); }
Each of them is as follows:
mapScene.owner.catalog.getGameSettings().axisMode = Yukar.Common.Rom.GameSettings.AxisMode.XZ;
mapScene.owner.catalog.getGameSettings().axisMode = Yukar.Common.Rom.GameSettings.AxisMode.XY;
To change the Maximum Capacity of the Inventory while the game is running, use GameMain.instance.data.party.inventoryMax.
This value is saved in the saved data, not in the Game Definition, so the next time it is loaded, the value will be the same as the changed value.
SEs can be changed by following the steps below.
var sound = catalog.getItemFromName<Yukar.Common.Resource.SoundResource>("Sound_Name"); Audio.UnloadSound(GameMain.instance.se.decide); GameMain.instance.se.decide = Audio.LoadSound(sound);
However, these are not eligible for saving to saved data and must be performed each time a change is made.
You can do so as shown below, but since the assignment to positionAnchorTag directly rewrites the Layout Tool's settings (which are then kept as rewritten) and does not take effect until the layout is redisplayed, it is better to use the Position operation.
var lyt = GameMain.instance.freeLayouts.FirstOrDefault(x => x.LayoutNode.Name == "ItemSelect"); if (lyt != null) { var node = lyt.LayoutDrawer.ParseNodes().FirstOrDefault(x => x.MenuItem.name == "Item Details"); node.Position = new Microsoft.Xna.Framework.Vector2(256, 256); // To move directly node.MenuItem.positionAnchorTag = "Rewrite Special Coordinate Tags"; }
You can access the currently displayed layout by the following ways.
[BakinFunction(Description = "Obtain the container management number of the selected subcontainer\nSet the action of the subcontainer to "Call Common Event" and call the following method in that event")] public int GetIndex() { // First, obtain the main menu manager var lc = mapScene.menuWindow as LayoutMenuController; var lm = lc.mainMenu; // Track and obtain open layouts derived from the main menu // (If it's being called from item select, it should end up in item select.) while (lm.NextlayoutManager != null) lm = lm.NextlayoutManager; // Obtain the currently selected index from the Drawer var drawer = lm.LayoutDrawer; GameMain.PushLog(DebugDialog.LogEntry.LogType.EVENT, "drawer", drawer.GetSelectIndex().ToString()); return drawer.GetSelectIndex(); }
Furthermore, if you wish to force the main menu to close after indexing, you can use the following method.
[BakinFunction] public void CloseMainMenu() { // First, obtain the main menu manager var lc = mapScene.menuWindow as LayoutMenuController; var lm = lc.mainMenu; lm.HideAll(); }
Incidentally, to obtain the currently selected index from a free layout, the following is used.
[BakinFunction] public int GetIndexForFreeLayout() { // First, obtain a free layout manager var lm = GameMain.instance.freeLayouts.FirstOrDefault(x => x.LayoutNode.Name == "Name of the Free Layout you want to obtain"); if (lm == null) { GameMain.PushLog(DebugDialog.LogEntry.LogType.EVENT, "drawer", "error"); return -1; } // Obtain the currently selected index from the Drawer var drawer = lm.LayoutDrawer; GameMain.PushLog(DebugDialog.LogEntry.LogType.EVENT, "drawer", drawer.GetSelectIndex().ToString()); return drawer.GetSelectIndex(); }
To look at GameMain.instance.freeLayouts.Count, please use the following.
// Hide all GameMain.instance.HideALLFreeLayout(mapScene.isBattle); // Show only selected layouts GameMain.instance.ShowFreeLayout(layoutGuid, mapScene.isBattle); // Add and display selected layouts GameMain.instance.AddFreeLayout(layoutGuid, mapScene.isBattle); // Hide selected layouts GameMain.instance.HideFreeLayout(layoutGuid, mapScene.isBattle);
Plug-in Reference: Use the Show/Hide methods in the Yukar.Engine.RenderContainer class description.
If animation is not required, ShowWithNotAnimation/HideWithNotAnimation can be used.
Search for "RenderContainer" in the Plug-in Reference to find the appropriate class.
https://rpgbakin.com/csreference/doc/ja/class_yukar_1_1_engine_1_1_render_container.html
The following method is available to prohibit cancellation.
Please try writing it in Update().
var menu = mapScene.menuWindow as LayoutMenuController; var lyt = menu.mainMenu; while (lyt.NextlayoutManager != null) lyt = lyt.NextlayoutManager; if (lyt.LayoutNode.Name == "SkillSelect") // In the SkillSelect section, put the name of the layout you want to target. { // Basically, it should be unlocked. if (lyt.IsLocked()) lyt.UnLock(); // Cancellation Prohibited if (Input.KeyTest(Input.StateType.TRIGGER, Input.KeyStates.CANCEL, Input.GameState.MENU) && !lyt.IsLocked()) lyt.Lock(); }
First, you must also specify a value for defaultPosition as follows.
(Also needs to access defaultPosition, so cast is also needed)
var node = lyt.LayoutDrawer.ParseNodes().FirstOrDefault(x => x.MenuItem.name == RenderContainerName) as RenderContainer; node.Position = node.defaultPosition = node.MenuItem.pos = new Vector2(scrnPosX, scrnPosY); // To move directly
When the sprite used for the animation switches, it gets the base coordinates from the layout data and updates them. It would be possible to achieve this by rewriting node.MenuItem.pos in addition to defaultPosition, but it would change the coordinates in Layout Tool. (This one is deprecated.)
Currently, the position is specified by SetLayoutPosition() only for the first time, but it would be possible to avoid this by rewriting defaultPosition for each frame during the display.
This is the case for the field named tags.
You can access it by the following.
catalog.getItemFromName<Yukar.Common.Rom.Cast>("Hero").tags
The skills that a cast member learns are in Cast.availableSkills. They can be obtained as follows.
var learnSkills = catalog.getItemFromName<Yukar.Common.Rom.Cast>("Ken").availableSkills;
Skills are stored in the form of GUIDs, so Achievement Level and the skills themselves can be obtained by further querying the Catalog as shown below.
if (learnSkills.Count > 0) { var skill = catalog.getItemFromGuid(learnSkills[0].skill) as Yukar.Common.Rom.NSkill; GameMain.PushLog(DebugDialog.LogEntry.LogType.EVENT, "C#", "Achievement Levels : " + learnSkills[0].level + " / Skill Name : " + skill.name); }
A complete list of all skills can be obtained by the following way.
var allSkills = catalog.getFilteredItemList<Yukar.Common.Rom.NSkill>().Cast<Yukar.Common.Rom.NSkill>();
You can obtain the EXP of the first monster by the following way.
BattleSequenceManagerBase.Get().EnemyViewDataList[0].monster.exp
You can also obtain the first drop item of the first monster by the following way.
var guid = BattleSequenceManagerBase.Get().EnemyViewDataList[0].monster.dropItems[0].item; var name = catalog.getItemFromGuid(guid)?.name;
When actually using the EnemyViewDataList or dropItems, check the upper limit by looking at the Count.
Please obtain rom from catalog as follows.
var rom = catalog.getItemFromGuid(guid) as Yukar.Common.Resource.SoundResource; Audio.LoadSound(rom);
BGM as a system has only one playback line, so it cannot be done with Audio.PlayBGM.
First, use the following method to start playback with zero volume as a sound effect (the loop setting is still reflected in this case).
var id = Audio.LoadSound(guid); Audio.PlaySound(id, 0, 0, 1);
Then use the following to manipulate the volume every frame to bring the volume of the new BGM closer to 1 while bringing the previous BGM closer to 0.
Audio.SetSEVolume(id, volume);
You can change it with the following code.
GameMain.instance.data.system.currentBattleCameraSet = "CameraSetName";
The camera will be reflected at the time of camera switching, but if you want it to be reflected immediately, you can use the following code.
mapScene.applyCameraToBattle();
Please note, however, that this is only effective from the C# assigned to the battle event.
First load the texture using the following code in Start(), for example.
tex = catalog.getItemFromName<Yukar.Common.Resource.Texture>(""TextureResourceName""); Graphics.LoadImage(tex);
Then, use the following at the scene you wish to render (Update, AfterDraw, etc.).
Graphics.DrawImage(tex, x, y);
After use, release the image used when the event is discarded as shown below.
public override void Destroy() { Graphics.UnloadImage(tex); }
It is available for use.
It can be used like mapChr.CreateEvent(guid, dir);.
mapChr.getDirectionRad() should be passed for dir if you want it to face the same direction as the source.
guid is the GUID of the cast.
It would be better to use catalog.getItemFromName("name of the cast you want to obtain").guId to find it and pass it.
Once a GUID is created for a cast, it does not change. Therefore, it is faster to write down the GUID by outputting a log, etc. and pass it without looking for it in the catalog by new Guid("GUID string").
getRelativeParam60FPS is the elapsed time from the previous frame converted to 60FPS.
In other words, this method returns the time taken for one frame (0.016666666 for 60FPS) multiplied by 60.
Within the C# script Update(), frameCount++; will add 1 to frameCount, and assuming no processing slowdown, it will be called 60 times per second, increasing by 60 per second.
However, this method will result in the addition of non-"60" values such as "30" or "120" per second when processing is slow or when the refresh rate is higher than 60.
Therefore, instead of frameCount++, frameCount += getRelativeParam60FPS() can be used to ensure that 60 is added per second even if the time taken per update is not 1/60 second.
Util.UnProject2World() is a method that converts XY coordinates on the screen to coordinates in 3D space.
Pass the projection and view matrices of the current camera.
Basically, assign mapScene.CurrentPP, mapScene.CurrentVV.
Input.KeyTest() is a method that obtains the state of the input device during a game.
The purpose is to simulate touch behavior, so it is processed to return such a value.
If you want unprocessed values, assign SYSTEM instead of WALK for GameState.
Since using setPositiion will reset velocity, instead, take the difference from the coordinates you want to correct and move the coordinates with the MapCharacter.Move method.
If the change is made from a C# script, it will be as follows
Camera
mapScene.CameraManager.ntpCamera
Key Frame
getKeyFrame()
DOF
Yukar.Common.Rom.Camera.KeyFrame.dof
X=Focal Coefficient, Y=Focal Range Coefficient, Z=Blurring Radius
Please note that changing the value using a C# script will rewrite the value specified in the Camera Tool.
The save slot number is obtained in var index.
[BakinFunction(Description = "Description")] public void Func() { var lc = mapScene.GetMenuController(); var lm = lc.mainMenu; var index = lm.SelectProp.SelectSaveIndex; }
var lm = lc.mainMenu will be if saved from the Main Menu.
If it was saved from an event with "Display Save Screen", change to lm = lc.save.