#scriptapiを教えてほしい
1 messages · Page 1 of 1 (latest)
いまは[scripting][error]-plugin[puchineko guns 2 -1.0.0] - does not contain main file [script/main.js].というエラーが出ています
scriptsファイル内にmain.jsを作成してください
sが抜けてるだけな気が
afterEventsのitemUseです
この鯖の過去ログやscriptapiについて書いてあるサイトなどあちこち見て見様見真似で組んだので怪しい部分もあります・・・(というか100%あってるのか怪しい)
銃こだわっててすごいな
scriptapiを使って
右クリックで発射 スニーク左クリックでタクティカルリロード
左クリックでモード切替 って感じで作りたいです・・・
空振り検知は不可・・・って感じですか?
そうですね
じゃああの鯖のアドオンはplayer.json使ったアドオン(操作系を参考にしようと思ってた)・・って感じですかね・・(ここでほかの鯖名・アドオン名を出すのはやめておきます)
銃弾が当たっちゃいますね・・・
そしたら攻撃通らなくなっちゃいますよね
空振りはアニコン使うしかないと思う
ブロックかエンティティかどっちか殴れば動くようにはできるんだけどね
ブロックに殴りだとどんな感じになります?
entityHitBlockで取れる
ありがとうございます 試してみます
source.runCommand
ここを変更して銃弾(プロジェクタイル)を飛ばしたいのですがどうすればいいでしょうか?
アイテムのイベントを呼んでshootを起動するとかじゃないですかね
データが多すぎて翻訳に時間がかかることがある
triggerEventメソッドがあります
ItemStackのtriggerEventを使ってますか?
あ・・・
sourceになってました・・・
[Scripting][warning]-[Watchdog] 129.349 ms script spike detected in behavior pack 'puchineko guns 2'
このエラーが出ます・・・
watchdogなので程々に気にすればいいです
import { world } from "@minecraft/server";
world.afterEvents.itemUse.subscribe( m16a1=> {
const { source, itemStack} = m16a1;
if(itemStack.typeId==='ar:m16'){
const ze = world.getPlayers();
source.runCommand(me @a m16a1)
itemStack.triggerEvent('m16shoot')
}
});
コードはこんな感じです
わかりました
runCommandが割とステート食ってる可能性は高いです
今はこのエラーが出て弾が出てないですね・・・
そのエラーと弾が出ないのは一切関係性はないですね
ええ・・・
ちなみにですがgetPlayersはなぜ書いてあるのですか
あとイベントを呼んでも動かないのはconditionを通過できていないからな気がします
一度shootだけのイベントを用意してみて使ってみてください
まだ動作していません・・・・
いくつか改良試したんですけどどれもダメでした・・
"testshoot":{
"sequence":[
{
"shoot":{
"projectile":"ar:m16bullet",
"launch_power":3
}
}
]
}
呼んでるイベントはこれです
パックの機能 'editorExtension' はサポートされていません。
エラーはパック画面でこれが出ています 実行時はエラー表示なしです
manifestを見せてください
capabilitiesからeditorExtensionをお外し下さい
ちなみにアイテムのイベントの方でsayコマンドとか実行した場合も動かないんでしたっけ?
動きませんね・・・
"testshoot":{
"sequence":[
{
"run_command":{
"command":[
"say @p"
],
"target":"holder"
}
}
]
}
eventの中身はこんな感じになってます
やっぱりitemStack.が必要だったんでしょうか?
triggerEventはItemStackに生えているメソッドなので必要ですね
そうすると今度はエラーないけど何も動かなくなっちゃうんですよね・・・
アイテムのjsonはこれですね・・・(m16shootイベントはscriptapi化前の残骸です)
ItemStackのtriggerEventメソッドは存在はしていますが、アイテムイベントは実行されず使えなかったはずです。
なのでアイテムイベントでやりたいこともスクリプト側で書いた方が良いかと
なるほどです・・・・
まだ治ってなかったんだ
"shoot":{
"projectile":"ar:m16bullet",
"launch_power":3
}
これとまだ未実装ですがlore管理の銃の残弾を減らす処理ですね・・・
プロジェクタイルを飛ばす処理ってありますかね・・・(なんとなくだけどない気がする・・・)
プロジェクタイルもエンティティなのでスポーンさせられます。<Entity>.applyImpulseなどで好きな方向に飛ばせます。
尚、この方法ではプロジェクタイルに誰が発射したかというデータがないため、キルログが「(プレイヤー名)に倒された」ではなく「(プロジェクタイル名)に倒された」になるなどの差はあります
ScriptAPIの開発者がプロジェクタイル関係でどんな機能があったら便利かを質問していたので、今後アイテムイベントの代わりにScriptでもプロジェクタイルを扱いやすくなるはずです
Entityにshootメソッド生やしてくれ
銃ごとに弾エンティティ分けてるから(撃たれたプレイヤー)は(銃の名前)で撃たれた
ってlangで設定すれば・・・
まあそれで良ければいいですが案件ですね(
他の方法があるとすれば発射したprojectileにタグ等を与えておきヒット時にダメージ処理をscriptAPI側で行うようにする とかですかね
scriptAPI側でダメージが自由にいじれる ダメージを与える際にタグを元に発射者を特定し発射者に攻撃されたことにできる等メリットもあります
アイテムのタグを使ってアイテムを追加するだけで弾の動作を設定する なんてこともできますね
弾丸自体の状態を変えようと思うといくつかのパターンを用意して…等にはなりますが
あー・・・・
実際突き詰めると銃弾は3種になりますね・・・・
1.普通の弾
2.グレネード弾
3.ロケット弾頭
(2と3は落下の仕方の違い)
まあscriptAPIから制御出来ない可変要素と言うとサイズくらいですけどね
ちなみに処理を完全にscriptAPIにするメリットのひとつとしてアイテム自体に依存した動作設計をするのでアイテムを増やすだけで10の種類がふやせる = 追加コンテンツを簡単に増やせる
というものもあります
もちろん用意した範囲内で ではありますがダメージ量やら発射間隔やら弾数やらは自由に設定出来ますし
なるほど・・・ 追加のアイテム用意しとけば特殊弾のマガジンのデータ+特殊弾用の処理用意すれば徹甲弾とか曳光弾とかの特殊弾薬を簡単に実装できる・・・
って認識でおkですか?
そんな感じにも可能ですね
当たったら貫通しろ とかprojectile自体に影響するものはprojectileの情報をいくつか用意するかあるいは別のprojectileにしておくなどが必要ではありますがタグを元に出すエンティティを変える なんて容易ですので
銃を作る気はないけどそんな感じの設計がしたくなってきた
現在のイメージとしては
銃ごとに残弾とかのデータ持たせる=>右クリック検知=>プロジェクタイルスポーン=>残弾データー1
残弾データ=0or地面をスニーク左クリック=>インベントリにマガジンあること検知=>リロード(残弾を初期値or初期値+1に)
って感じですね
このタグってコマンドでつけるほうのタグですか?
タグ≠データ値 で合ってますかね?・・・・
?
アイテムに付けるタグとtagコマンドでこんがらがってますね・・・・
projectileに与えるのはコマンドの方のタグで武器の動作分岐はアイテムにつけるタグですね
コマンドのほうのタグは発射したプレイヤー名を持たせる
アイテムのタグは銃の状態を持たせる
って感じで合ってます?
例えば僕が撃った銃弾はDisloyalSquid93ってタグが付くってことですかね?
例えばそんな感じですね
タグの内容を取得=>当たったプレイヤーに僕から相手へ飛び道具で与えたとしてダメージ処理
って感じですかね?
そんな感じですね
これだったら (撃たれたプレイヤー)はDisloyalSquid93に倒された って感じかな?
applyDamageで発射者を指定する感じですね
銃の種類も取得して (撃たれたプレイヤー)は(撃ったプレイヤー)の(銃の種類)で撃たれた ってのも可能ですか?
(langもいじらないといけないし多分実装するのかなり先)
キルログを消す必要がありますが消してしまえばあとは出したいように出すだけではありますね
||僕の場合はとりあえず発射とか残弾とかの基礎部分作るのが先ですね・・・||
scriptapiでエンティティをsummonごり押し以外で出す方法ってありますか?
(現在summonごり押し実装ですw)
Dimension.spawnEntity()が使えます
Dimensionにはエンティティを出したいディメンションを入れてください
全ディメンションで出したい場合は全ディメンション分やる感じですか?
イベントのsourceに入っているPlayerから source.dimension のようにして使った人のディメンションを取得できるので
そこからspawnEntityに繋げてみてください
world.afterEvents.itemUse.subscribe( ak47=> {
const { itemStack} = ak47;
const { source} = source.dimension;
if(itemStack.typeId==='ar:ak47'){
source.spawnEntity('ar:ak47bullet')
}
});
こんな感じですか?
sourceはイベント変数のak47から取得します
const { source} = ak47 で合ってますか?
⭕
エラー出ますね・・・
world.afterEvents.itemUse.subscribe( ak47=> {
const { itemStack} = ak47;
const { source} = ak47;
if(itemStack.typeId==='ar:ak47'){
const ze = world.getPlayers(source.dimension);
source.Dimension.spawnEntity('ar:ak47bullet')
}
});
コードこんな感じです
dimensionのdは小文字です
この手のポカミス初めからめっちゃやってるな・・・
const { itemStack, source } = ak47;のようにまとめて書くこともできます
またエラー出ました・・
world.afterEvents.itemUse.subscribe( ak47=> {
const { source,itemStack} = ak47;
if(itemStack.typeId==='ar:ak47'){
const ze = world.getPlayers(source.dimension);
source.dimension.spawnEntity('ar:ak47bullet')
}
});
今のコードです
sourceがプレイヤーを指しているのでgetPlayersは不要です
const ze = world.getPlayers(source.dimension);
この行自体が不要ってことでおkですか?
はい
そうするとこのエラーが出ますね・・・
world.afterEvents.itemUse.subscribe( ak47=> {
const { source,itemStack} = ak47;
if(itemStack.typeId==='ar:ak47'){
source.dimension.spawnEntity('ar:ak47bullet')
}
});
spawnEntityの2つ目の引数に座標を渡さないとでした
自分の視点の先に出したいときはどうすればいいですか?
自分の座標にZ+1くらいのほうがいいかもですね・・・
こうなりました
あーだめですね()
そっこーで銃弾に視点の方向に加速度かければ行けますかね?・・・
先に飛ばす処理書いてみますか
ですね
spawnEntity()の返り値が出したエンティティになるので
このように変数に入れてあげましょう
const bullet = ...spawnEntity(...)
(...は略)
そうするとbullet.applyImpluse()のように書けます
world.afterEvents.itemUse.subscribe( ak47=> {
const { source,itemStack} = ak47;
if(itemStack.typeId==='ar:ak47'){
source.dimension.spawnEntity('ar:ak47bullet',source.getHeadLocation());
const bullet = source.dimension.spawnEntity('ar:ak47bullet',source.getHeadLocation());
bullet.applyImpluse(15)
}
});
こんな感じですね・・・
16行目はどこですか?
impulse
プレイヤー使えないからね しょうがないね
こんな感じで見ている方向に速度を与えられます
const speed = 3;
const impulse = Vector.multiply(player.getViewDirection(), speed);
bullet.applyImpulse(impulse);
speedの値はいじってみてください
const { source,itemStack} = ak47;
if(itemStack.typeId==='ar:ak47'){
source.dimension.spawnEntity('ar:ak47bullet',source.getHeadLocation());
const bullet = source.dimension.spawnEntity('ar:ak47bullet',source.getHeadLocation());
const speed = 3;
const impulse = Vector.multiply(player.getViewDirection(), speed);
bullet.applyImpulse(impulse);
}
});```
エラー出てしまいますね・・・
const { source,itemStack} = ak47;
if(itemStack.typeId==='ar:ak47'){
const bullet = source.dimension.spawnEntity('ar:ak47bullet', source.getHeadLocation());
const speed = 5;
const impulse = Vector.multiply(source.getViewDirection(), speed);
bullet.applyImpulse(impulse);
}
});```
こんな感じで合ってますか?
そんな感じですかね
このエラーが出ていますね・・・
importにVectorを追加してください
行けると思います
フルオートはifでアイテムに記録した射撃モードをチェック=>右クリック押しっぱなし検知=>発射コードをループ
切り替えは左クリック検知=>アイテムに書き込み
ってできますか?
実装方法は様々ですが私であれば発射処理部分を同一にするためイベントからプレイヤー等の情報を配列上に放り込み runIntervalからそのデータを参照 単発なら発射後削除 連射なら維持 離した際のイベントから削除 という形にしますね
まあやりやすいやり方でいいかと
この場合って持ってるすべての銃で射撃モードって共有になりますか?
(現状の計画だと6パターンくらい射撃モードのパターンあるので・・・)
・セミオートオンリー
・フルオートオンリー
・セミオート フルオート切り替え
・セミオート フルオート グレネードランチャー切り替え
・セミオート 3点バースト フルオート切り替え
・単発銃
どうとでもなるかと
特にその必要はないです
スポーンさせる位置を視点方向に少しずらしてみましょう
const spawnLocation = Vector.add(source.getHeadLocation(), source.getViewDirection());
const bullet = source.dimension.spawnEntity('ar:ak47bullet', spawnLocation);
これでちょうど1ブロック先に出てくるはずです
マルチでもしっかり動作しました ありがとうございます!
このやり方でセミ・フル切り替え機能を付ける前にまずはフルオートで撃てるようにしておこうかな=>色々ググった結果で組んでみる=>現状って感じですね・・・
setDynamicPropertyはこのように使います
<Player>.setDynamicProperty("キー", 値);
world.afterEvents.itemStopUse.subscribe
iは小文字です
runInterval内で未定義の変数が使われています
消す時はundefined(=何も書かない)を入れます
<Player>.setDynamicProperty("キー");
<Player>の場所にはただplayerを入れるのではなく適切な変数名を入れる必要があります
itemUseイベント内では使ったプレイヤーをsourceプロパティから取得し変数に定義しているので、ここでは source.setDynamicProperty() のように書くのが適切です
runInterval内でsourceが未定義なのが原因です
プレイヤーが渡されるイベント以外の場所でプレイヤーに処理をする場合は
world.getPlayers()やworld.getAllPlayers()などを使って全プレイヤーを取得し、for ofなどを使用してそれぞれに対して処理を行います
EX:```js
system.runInterval(() => {
for (const player of world.getPlayers()) { // 全プレイヤーを取得し、それぞれを"player"として定義
player.sendMessage('hi'); // 全プレイヤーにメッセージが送られる
}
});
今のところdynamicplopaty以外には特に何も射撃時に書き込まれません
エラーのほうは自己解決しましたが・・・ 射撃止まんなくなりました・・・
itemStopUseでダイナミックプロパティが変わって射撃止まるはずなんですが・・・
なぜか止まりません・・・
それは謎🤔
uuid変えて入れなおしたら直りますかね?
変えても同じことが起きる気はしますが...
そもそもitemStopUseは発生しているのですか
stopUseが発生していないならそれが原因でしょう
アイテムに使用する要素がなければストップもないと思います
アイテムにon use があったんですけど・・・ scriptapiに改造時に消しましたね・・・
アイテムのほうにfoodとかの右クリックで何か起きるコンポーネントつけとけばいい感じですか?
アプデ後色々ぶっ壊れたみたいで全く動きません・・・
akが表示されない+アイコンが全部出てないですね・・・ あとは右クリックのコンポーネントが反応してないです・・・
1.20.41ですね・・・ (前のテストしてたバージョンは1.20.40ですね・・・)
結構エラー吐いたりしてますし・・・(エラー出すぎて問題の部分が見えないレベル)
アドオンに関する変更点皆無ですね チェンジログ上は ですが
41の変更点は
・realms関連のクラッシュバグ修正
・マケプレ関連のバグ修正
・PlayStationでデモからフルバージョンにアップグレードできない問題を修正
だけですね
manifestを作り直したら直りました・・・(たまにこれで治るけど普通に謎)
自己解決しました
https://qiita.com/JUN-SUZU/items/bd8c13b4ebf5c600bc9b
これをベースに残弾システムを作ろうと思っているのですがプレイヤーの今持っているアイテムにloreを付ける部分と
scoreboardに今持ってるアイテムのloreに保存されてる残弾を代入する方法をおしえてもらえないでしょうか?
18行目で undefined に getDynamicProperty は存在しない、というエラーです。
(entityHitBlockイベントでの source.getDynamicProperty の source が undefined)
entityHitBlockイベントにはsourceプロパティはありません、あるのは blockFace、damagingEntity、hitBlockだけです。
https://learn.microsoft.com/ja-jp/minecraft/creator/scriptapi/minecraft/server/entityhitblockafterevent?view=minecraft-bedrock-stable
プレイヤーを取っていないのでエラー・・って感じですか?
sourceはないですがEntity自体はdamagingEntityにありますよ
ここは値を持っていないことを条件にするなら!で反転させるかundefinedと比較ですね
source.getDynamicProperty("m16a1mode")===''
damagingEntityとかが無くなってるような
if(damagingEntity.getDynamicProperty("m16a1mode")===undefined){
source.setDynamicProperty("m16a1mode")
}
for(const source of world.getPlayers())
if(source.getDynamicProperty("m16a1mode")===''){
source.setDynamicProperty("m16a1mode",'auto')
}```
ここですか?
これtrueたりうるのか?
''を設定してれば話は別だが
とりあえずこれと
damgingEntityが二重で存在するのと
ワールド内のプレイヤーを取得する必要があるのか という疑問があります
2つ目のifをelse ifにしておかないとautoをセットした後にautoを比較してしまって消されてしまいますね
それと最初のifのせいでautoだった場合最初のifを通過しないのでその後のautoとの比較まで行かないかと
const { damagingEntity} = m16;
if(damagingEntity.getDynamicProperty("m16a1mode")===undefined){
damagingEntity.setDynamicProperty("m16a1mode",'auto')
}
else if(damagingEntity.getDynamicProperty("m16a1mode")==='auto'){
damagingEntity.setDynamicProperty("m16a1mode")
}
});}```
こんな感じですか?
最後のカッコが気になりますがそんな感じですね
現状はこんな感じになっていて
(残弾をアクションバーに表示する用の)スコアボードにloreの一部の行に保存した残弾を代入して残弾=0になるorスニーク右クリックで初期値に残弾を変える・・・って処理を考えたのですが・・・
addScore(participant: Entity | ScoreboardIdentity | string, scoreToAdd: number): number
これを使う・・・くらいしか・・・
教えてもらえると嬉しいです
代入ならsetScoreでいいかと
https://qiita.com/JUN-SUZU/items/bd8c13b4ebf5c600bc9b
loreの部分はこれを参考にしようと思ってます
import { world, system, Vector } from "@minecraft/server";
world.afterEvents.itemUse.subscribe(m16 => {//射撃開始
const { source, itemStack } = m16;
if(itemStack.typeId === 'ar:m16') {
source.setDynamicProperty("m16a1", 'fire');
}
});
world.afterEvents.itemUse.subscribe(ak47=> {//後でセミ・フル切り替えに修正
const { source, itemStack } = ak47;
if(itemStack.typeId==='ar:ak47') {
const spawnLocation = Vector.add(source.getHeadLocation(), source.getViewDirection());
const bullet = source.dimension.spawnEntity('ar:ak47bullet', spawnLocation);
const speed = 5;
const impulse = Vector.multiply(source.getViewDirection(), speed);
bullet.applyImpulse(impulse);
}
});
world.afterEvents.itemUse.subscribe( m1911a1=> {//モード切替がないセミオートオンリー銃
const { source, itemStack } = m1911a1;
if(itemStack.typeId==='hg:m1911') {
const spawnLocation = Vector.add(source.getHeadLocation(), source.getViewDirection());
const bullet = source.dimension.spawnEntity('hg:m1911bullet', spawnLocation);
const speed = 5;
const impulse = Vector.multiply(source.getViewDirection(), speed);
bullet.applyImpulse(impulse);
}
});
world.afterEvents.itemStopUse.subscribe(m16 => {//射撃終了
const { source, itemStack } = m16;
if(itemStack.typeId === 'ar:m16') {
source.setDynamicProperty("m16a1");
}
});
world.afterEvents.entityHitBlock.subscribe(m16 => {//モード切替
const { damagingEntity } = m16;
switch(damagingEntity.getDynamicProperty("m16a1mode")) {
case 'semi':
damagingEntity.setDynamicProperty("m16a1mode", 'auto');
break;
case 'auto':
damagingEntity.setDynamicProperty("m16a1mode", 'semi');
break;
}
});
system.runInterval(function() {
for (const player of world.getPlayers()) {
if(player.getDynamicProperty("m16a1") !== 'fire') continue;
const spawnLocation = Vector.add(player.getHeadLocation(), player.getViewDirection());
player.runCommand(`playanimation @s animation.item.m16a1.shoot`)
const bullet = player.dimension.spawnEntity('ar:m16bullet', spawnLocation);
const speed = 5;
const impulse = Vector.multiply(player.getViewDirection(), speed);
bullet.applyImpulse(impulse);
if(player.getDynamicProperty("m16a1mode") === 'semi') {//セミオート
player.setDynamicProperty("m16a1");
}
}
}, 5);
最低限の修正のみしました
ちなみにですがLoreをスコアに入れたい理由は何ですか?
アクションバーに残弾を表示するためです
titlerawでスコアボードを表示する・・くらいしか思いつかなかったので・・・
onScreenDisplayから直接アクションバーに書き込みができるのであとは残弾管理処理も混じえて表示でもいいとは思います
スコアで弾数管理したい とかならそれもありだとは思います
修正ありがとうございます
処理の統一もしようかと思ったんですがまあどのような処理になるかとか今後どのような処理が増えるのかとかが不明なのでひとまずはこのくらいにしました
質問とは関係ないですがitemUseイベントやgetPlayersの処理は一つにまとめた方がいいと思います
射撃モードの種類が同じ銃は同じ処理にまとめたほうがいい感じですか?
銃器の処理を大雑把に捉えると基本的には
弾丸Aを速度BでC方向に飛ばす
といったふうに可変的な部分を持つ同一の表し方ができるものだと思います
↑射出の処理はこうまとめれると思います
あとは使用の仕方が違う 等がなければ銃nを使用しているなら使用しているフラグを立てる
使用を辞めたなら使用しているフラグを落とす といった部分は同一の処理でいいと思います
なるほど・・・
https://tn-docs-test.vercel.app/articles/1.20.60-changelog
これのitemstackdynamicplopatyって実験機能がオンのワールドなら使える感じですか?
1.20.60の主な変更点です(preview.23時点)
(もしアプデ待たないと使えないならアプデ待つつもりです)
previewなら使えると思うよ
少なくとも来るのは1月下旬らへんかなぁ
アプデ来たので速攻で
EntityProjectileComponent
を用いたコード改良をしてみましたが・・・
ItemStack Dynamic Propertyがよくわからない感じですね・・・
itemStack.setDynamicProperty(" ");
みたいに書けばいい感じですか?
そんな感じです
なるほどです
すでに入ってる数値から-1したい場合は
itemStack.setDynamicProperty("m16a1ammo",'m16a1ammo'-1)
こんな感じで合っていますか?
system.runInterval(function() {
for (const player of world.getPlayers()) {
if(player.getDynamicProperty("m16a1") !== 'fire') continue;
const spawnLocation = Vector.add(player.getHeadLocation(), player.getViewDirection());
player.runCommand(`playanimation @s animation.item.m16a1.shoot`)
const m16a1bullet = player.dimension.spawnEntity("ar:m16bullet", spawnLocation);
const projectile = m16a1bullet.getComponent("minecraft:projectile");
const velocity = Vector.multiply(player.getViewDirection(), 5);
projectile.shoot(velocity);
const ammo =itemStack.getDynamicProperty("ammo")
ammo = Number(ammo);
itemStack.setDynamicProperty("ammo", ammo-1);
if(player.getDynamicProperty("m16a1mode") === 'semi') {//セミオート
player.setDynamicProperty("m16a1");
}
}
}, 5);
こんな感じですか?
(||僕の中途半端な||知識総動員して書きました)
メインハンドののアイテムを取るにはどうすればいいですか?
インベントリからselectedSlotのindexで取得するかequippableからMainhandを取得するかのどちらかです
system.runInterval(function() {
for (const player of world.getPlayers()) {
if(player.getDynamicProperty("m16a1") !== 'fire') continue;
const spawnLocation = Vector.add(player.getHeadLocation(), player.getViewDirection());
player.runCommand(`playanimation @s animation.item.m16a1.shoot`)
const m16a1bullet = player.dimension.spawnEntity("ar:m16bullet", spawnLocation);
const projectile = m16a1bullet.getComponent("minecraft:projectile");
const velocity = Vector.multiply(player.getViewDirection(), 5);
projectile.shoot(velocity);
const itemStack = equipmentCompPlayer.getEquipment(EquipmentSlot.Mainhand, new ItemStack(MinecraftItemTypes.ar:m16));
itemStack.setDynamicProperty("ammo", ammo-1);
if(player.getDynamicProperty("m16a1mode") === 'semi') {//セミオート
player.setDynamicProperty("m16a1");
itemStack.setDynamicProperty("ammo", ammo-1);
}
}
}, 5);
これだとコードエディターの時点でエラー吐きますね・・
(銃のアイテムIDはar:m16です)
既に手に持っているアイテムを取得するので新しくItemStackを作る必要はありません
...getEquipment(EquipmentSlot.Mainhand);でok
わかりました
アイテムごとに処理を分岐させるのであればitemStack.typeIdを条件に分岐させてください
発射部分を共通化してアイテムidで分岐させるのと発射モードカテゴリ別にそれぞれに処理するのどっちがいいんでしょうか・・・
(銃としては大きくカテゴリ分けすると射撃モード別で5種あります セミ セミ・フル セミ・フル・バースト フル セミ・フル・ランチャー)
射撃モードによって何が変わるんですか?
切り替えのパターン がよく分かりませんがオブジェクトで一括管理すると良さそうです
例えばこのように定義しておくと```js
const gunData = {
"ar:m16": {
animation: "animation.item.m16a1.shoot",
bullet: "ar:m16bullet",
propertyId: "m16a1mode",
modes: {
"auto": { speed: 5 },
"semi": { speed: 3 }
}
},
"アイテムID": { ... }
}
このように1つのコードで複数の銃に対応できます
```js
const data = gunData[item.typeId]; // IDに対応する銃のデータを取得
if (data) {
player.runCommand(`playanimation @s ${data.animation}`);
...
const bullet = player.dimension.spawnEntity(data.bullet, spawnLocation);
...
const mode = player.getDynamicProperty(data.propertyId);
const speed = data.modes[mode].speed;
const velocity = Vector.multiply(..., speed);
projectile.shoot(velocity);
}
semiモードが単発射撃 autoモードが連射ですね・・・
dataとmodeが未定義です
これ前から思ってたけどfireをDPに保存する必要ってないよな
銃のデータを別ファイルに置くことってできますか?
main.jsを処理 別ファイルをデータ置き場にしたいのですが・・・
別のjsファイルを作りexportすることで、main.jsでimportして扱うことができます
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/export
こんな感じですか?
現状こんな感じですね・・・ 弾の代わりにエラーが出ます・・・
動作しないですね・・・
[Scripting][error]-ReferenceError: 'item' is not defined at <anonymous> (main.js:49)
エラーはこんな感じです・・・
こっちは自力で解決しました
今はこっちのエラーだけ出てる感じです
このエラーはitemが未定義 というエラーです
使用している場所を見てきちんと定義されているか確認してみてください
const data = gunData[itemStack.typeId]; // IDに対応する銃のデータを取得
これを参考に||(というよりそのまま利用)||した感じですね・・・
マイクラからitemをインポートすればいい感じですか?
このitemはおそらく使用したアイテムのことだと思います
itemStackに書き換えたほうがいいですか?
itemStackで定義されているならそういうことです
今度はエラーも弾も出なくなりました・・
使用しているのは上のファイルですか
エラー見たら単純に書き間違いでした・・・
エラーは直しましたがまだ弾は出ないですね・・・
使用しているのはこれです
DPのammoの初期値は9行目で登録しているはずなんですが・・・
52行目を見てください
detaとdataのタイポ
const ammo = itemStack.setDynamicProperty("ammo")//現在の装弾数を取得
setしてますね
ただ、import文で相対パス指定をしないと参照する場所がズレた気がするので相対パス指定にした方がいい気がします
同じ回送なのでファイル名になってますが・・・ ../scripts/deta.jsにしたほうがいい感じですか?
エラーは
なしです
ならどこまで動いているかを確認してください
一切動いてない感じですね・・・
射撃処理で弾が入ってない場合はno ammo
弾がある場合は”残弾”/最大装弾数
とコマンドで出るはずなので・・・
なのでどこまで動いているのかを確認してください
メッセージを同じにしたらどこが出してるか分からないです…
これで動いていないのはrunIntervalのどこかであることがわかったはずです
もっと細分化しどこまで動いているかを確認してください
ついでに使用している値も出力するといいでしょう
sourceにsetItemはありません
どうすればいいですか?
個人的にはsetItemするよりContainerSlotを使った方がいい気がします
world.afterEvents.itemUse.subscribe(m16 => {//射撃開始
const { itemStack,source } = m16;
if(itemStack.typeId === 'ar:m16') {
source.runCommand(`say start`)
itemStack.setDynamicProperty("gun", 'fire');
itemStack.setDynamicProperty("ammo", 30);
ContainerSlot.setItem(itemStack?:m16);
}
});
こんな感じですか?
ContainerSlotはいったいどこから来たのですか
<Container>.getSlot(index: number): ContainerSlotです
メインハンドのアイテムだとどうなりますか?
<Player>.selectedSlotを使用してください
world.afterEvents.itemUse.subscribe(m16 => {//射撃開始
const { itemStack,source } = m16;
if(itemStack.typeId === 'ar:m16') {
source.runCommand(`say start`)
itemStack.setDynamicProperty("gun", 'fire');
itemStack.setDynamicProperty("ammo", 30);
source.setItem(index,m16:source.selectedSlot);
}
});
これはコードエラー・・・
ちなみにgetSlotならsetItemが不要になります
イベントから取ってるのはItemStackなのでDPをセットしたあとsetItemが必要です
source.setItem(source.selectedSlot,itemStack);
これをDPいじった後すべてに入れる感じですか?
DynamicPropertyの操作は全てContainerSlotから可能なので書き換えてあげましょう
そうすればgetEquipmentもsetItemも要らなくなります
ContainerSlot.setitem(slot.selectedSlot,itemStack);
みたいな感じですか?
setしなくていいです
ContainerSlotは書き換えるとすぐに値が反映されるものです
なるほどです
sourceにsetItemはありません
ContainerSlot(slot.selectedSlot,itemStack);はいりません
runInterval内でしているItemStackの操作は全てContainerSlotで可能です
つまりitemStack.〇〇と書いているものはslot.〇〇と書き換えられます
↑
イベント内ではitemStackに対してDynamicPropertyの操作などをしているので、それらを保存するために<Container>.setItemが必要です
world.afterEvents.itemUse.subscribe(m16 => {//射撃開始
const { itemStack,source,ContainerSlot,slot } = m16;
if(itemStack.typeId === 'ar:m16') {
source.runCommand(say start)
itemStack.setDynamicProperty("gun", 'fire');
itemStack.setDynamicProperty("ammo", 30);
ContainerSlot.setItem(slot.selectedSlot,itemStack);
}
});
こっちはこんな感じですか?
<Container>.setItemです
selectedSlotはPlayerのプロパティ(=source)です
Containerはインベントリコンポーネントを取得し、<InventoryComponent>.containerから取得します
world.afterEvents.itemUse.subscribe(m16 => {//射撃開始
const { itemStack,source,ContainerSlot } = m16;
if(itemStack.typeId === 'ar:m16') {
source.runCommand(say start)
itemStack.setDynamicProperty("gun", 'fire');
itemStack.setDynamicProperty("ammo", 30);
const inventory = player.getComponent(EntityInventoryComponent.componentId);
inventory.setItem(source.selectedSlot,itemStack);
}
});
こんな感じですか?
inventory.container.setItemですね
world.afterEvents.itemUse.subscribe(m16 => {//射撃開始
const { itemStack,source,player } = m16;
if(itemStack.typeId === 'ar:m16') {
source.runCommand(say start)
itemStack.setDynamicProperty("gun", 'fire');
itemStack.setDynamicProperty("ammo", 30);
const inventory = player.getComponent(EntityInventoryComponent.componentId);
inventory.container.setItem(source.selectedSlot,itemStack);
}
});
こんなエラーが出てますね・・・
[Scripting][error]-TypeError: cannot read property 'getComponent' of undefined at <anonymous> (main.js:11)
world.afterEvents.itemUse.subscribe(m16 => {//射撃開始
const { itemStack,source } = m16;
if(itemStack.typeId === 'ar:m16') {
source.runCommand(say start)
itemStack.setDynamicProperty("gun", 'fire');
itemStack.setDynamicProperty("ammo", 30);
const inventory = source.getComponent(EquipmentSlot.Mainhand);
inventory.container.setItem(source.selectedSlot,itemStack);
}
});
現在はこのエラーです・・・
[Scripting][error]-TypeError: cannot read property 'container' of undefined at <anonymous> (main.js:12)
world.afterEvents.itemUse.subscribe(m16 => {//射撃開始
const { itemStack,source } = m16;
if(itemStack.typeId === 'ar:m16') {
source.runCommand(say start)
itemStack.setDynamicProperty("gun", 'fire');
itemStack.setDynamicProperty("ammo", 30);
const inventory = source.getComponent(EntityInventoryComponent.componentId);
inventory.container.setItem(source.selectedSlot,itemStack);
}
});
現状こんな感じですね・・・
EntityInventoryComponentはインポートしてください
これまで教えてもらったこと+自分で調べたことで修正しましたが…まだエラー出ます・・
https://jaylydev.github.io/scriptapi-docs/1.20.60/classes/_minecraft_server_1_7_0.EntityHitBlockAfterEvent.html
そういえばentityHitBlockにsourceとitemStackはありませんでしたね(
Documentation for Script API - v1.20.60
PlayerはdamagingEntityから取ってください
アイテムについてはrunInterval内と同じくContainerSlotを取得してsetDynamicPropertyすると扱いやすいと思います
エラー出なくなりました!
あとはこちらですね
world.afterEvents.entityHitBlock.subscribe(m16 => {//モード切替・リロード
const { damagingEntity } = m16;
const equipmentCompPlayer = damagingEntity.getComponent(EntityComponentTypes.Equippable);
const itemStack = equipmentCompPlayer.getEquipment(EquipmentSlot.Mainhand);
const inventory = damagingEntity.getComponent(EntityInventoryComponent.componentId);
const maxammo =gunData[itemStack.typeId.maxammo];
const isSneaking = damagingEntity.isSneaking; // スニークしているか(true/false)
if(isSneaking==true){
if(itemStack.getDynamicProperty("ammo") >=1){
itemStack.setDynamicProperty("ammo", maxammo+1);
}else{
itemStack.setDynamicProperty("ammo", maxammo);//スニーク左クリックでリロード
}
inventory.container.setItem(damagingEntity.selectedSlot,itemStack);
}else{
switch(itemStack.getDynamicProperty("mode")) {
case 'semi':
itemStack.setDynamicProperty("mode", 'auto');
inventory.container.setItem(damagingEntity.selectedSlot,itemStack);
break;
case 'auto':
itemStack.setDynamicProperty("mode", 'semi');
inventory.container.setItem(damagingEntity.selectedSlot,itemStack);
break;
case 'undifined':
itemStack.setDynamicProperty("mode", 'semi');
const mode = itemStack.getDynamicProperty("mode")
player.runCommand(`say ${mode}`)
inventory.container.setItem(damagingEntity.selectedSlot,itemStack);
break;
}
}
});
現在これと残弾減らす処理が動いてない感じですね・・・(しかもエラーなしで)
ContainerSlotよりもItemStack使いたい感じですかね...?
そういえばテストした時にアイテムが更新される関係かアニメーションに乱れがあったので気をつけてください
そうですね・・・
僕的にはそっちのほうがわかりやすかったので・・・
現状発射されたりされなかったり残弾減ったり減らなかったりですね・・・
ItemStackとContainerSlotにそこまで大きな違いは無いと思いますけどね
getItemがgetSlotになって後からsetItemする必要がなくなるだけではある()
ここはconst maxammo = gunData[itemStack.typeId].maxammo;です
case 'undifined':のところ
undefinedは文字ではないので case undefined: に変えてみてください
改良しました
残弾の保存を射撃終了時に置き換えようと思うのですがどうすればいいですか?
う~ん・・・
runinterval内でconstに書き込んでitemstopuseでrunintervalで設定したconstをsetdynamicpropertyでやる・・・っての思いついたんですが・・・
処理イメージ
最後の円柱はconst ammoをDPammoに書き込みの間違いです
こんな感じで残弾が減らずに発射されたり超連射始まって荒ぶったりするのでこの処理思いついたのですが・・・・
これの対処法ってありますか?
runIntervalの処理が上手くいってない感じ...?
そうですかね・・・・・
とりあえず動作してないという事実だけが残ってますね・・・
数か所タイプミスあったので修正しましたが・・・
やっぱり動いてません・・・(弾は出ます)
動作的には
射撃開始時にアイテムのDP ammoをプレイヤーのDP nowammoに書き込み
1発撃つごとにプレイヤーのDP nowammoを-1
射撃終了時にプレイヤーのDP nowammoをアイテムのDP ammoに書き込みです
今ちょっと荷解き中なのであれですが後で確認してみます
ar:m16以外のデータにはreloadプロパティが存在していないですね。読んでないか。m16でもアニメーションが動きませんか?またエラーは出ていますか
animation.item.m16a1.reloadは素で発動して動作しますか
あれ・・・ 動作しませんね・・・(scriptapi化する前の銃アドオンからモデルとかアニメーション周り全部移植したんですが・・・)
それを治したら動いてくれるんじゃないかなあと思います…アニメーションは私には分かりません
なぜかanimation.item.m16a1.reloadだけ再生されないんですよね・・・
どう修正すればいい感じですか?
せめてエラーがあるのかと、どの段階の動作が機能していないのかくらいの情報を書いた方が良いと思います
一切エラーないですね・・・
おそらく if(itemStack.getDynamicProperty("mode") === 'semi') {//セミオート
player.setDynamicProperty("gun");
}
がどう出してない感じかと・・・
modeのセットが出来てないのかな
そのときgunはfireですか?
19にも同じのがあるようですね
ええ・・・
gunDataが不明なので憶測ですが
gunDataは銃のIDとか装弾数とかが記録されてるデータファイルです
data.jsに保存されています
まあどちらにせよgunDataの中身が例えば
{
"gun:gun_1": "gun:gun_1"
}
とでもなってない限りこのifは通れないです
この辺の
こんな感じにすればいいですか?
条件が無くなったのでスタックできるアイテムを持っていた場合エラーになりますね
前のコードに戻してdata.jsに追加すればいい感じですか?
問題ないです
あと修正する場所ってありますか?
不要コードのコメントアウトをしましたが・・・(コメントアウトなのは発射用の最低限のコードになっているため)
マルチで動作してません・・・
状況としてはは残弾表示が消えて銃弾も出なくなります・・・
エラーは出ていませんか
残弾表示はrunInterval内の処理のようなので、全プレイヤーのループ処理中にエラーが出て止まっているのではないでしょうか→マルチだと動かない
system.runInterval(function(shoot) {//射撃処理
for (const player of world.getPlayers()) {
const equipmentCompPlayer = player.getComponent(EntityComponentTypes.Equippable);
const itemStack = equipmentCompPlayer.getEquipment(EquipmentSlot.Mainhand);
const maxammo = gunData[itemStack.typeId].maxammo;````gunData[itemStack.typeId]`が`undefined`の可能性があります、その状態で`gunData[itemStack.typeId].maxammo`とするとエラーになるでしょう。例えば銃を持っていないプレイヤーがいるとその人以降の処理がエラーで止まってしまいます。
`function (`~~shoot~~`) {` ~~shoot不要~~
なるほどです
プレイヤーごとに処理すればいい感じですか?
そもそもエラーを出さないようにしてください
何も変わっていないですね
ここで指摘されたmaxammoの後に分岐しているので意味がないですね
なるほど・・・
constより前にif持ってくる感じですか?(マルチプレイの検証が相方の都合でできてないので・・・)
itemStackを得なければtypeIdも得られないのでそれより後ではあります。具体的にはdataを取得した直後にdataがあるかを確認するのが無難な気がしますが、maxammoを少し動かす必要がありますね
そういえば引数にshootが残ったままですね
なるほどです
修正してみます
system.runInterval(function() {//射撃処理
for (const player of world.getPlayers()) {
const equipmentCompPlayer = player.getComponent(EntityComponentTypes.Equippable);
const itemStack = equipmentCompPlayer.getEquipment(EquipmentSlot.Mainhand);
if(gunData[itemStack.typeId]!=undefined){
const maxammo = gunData[itemStack.typeId].maxammo;
const data = gunData[itemStack.typeId]; // IDに対応する銃のデータを取得 ←ココ````const data`で`gunData[itemStack.typeId]`を代入しているなら
```js
system.runInterval(function() {//射撃処理
for (const player of world.getPlayers()) {
const equipmentCompPlayer = player.getComponent(EntityComponentTypes.Equippable);
const itemStack = equipmentCompPlayer.getEquipment(EquipmentSlot.Mainhand);
const data = gunData[itemStack.typeId]; // IDに対応する銃のデータを取得
if(data!=undefined){
const maxammo = data.maxammo; // gunData[itemStack.typeId]をdataと短く書ける```こうやって利用すればより良く書けるのではと思わなくもないですが、一応そのコードでその場所のエラーは無くなるのではないでしょうか
試してご確認してください
リロード時にconst guntypeにリロードしている銃のデータを入れてリロード処理用の銃に置き換えた後にconst guntypeに記録したデータで元の銃に戻すって処理を書きたいのですが最後の部分が認識されません(constの表示部分が薄いままになります)
スコープの問題ですね。if内で宣言したGuntypeを外から参照はできません
わかりました 修正してみます
49行目closeが未定義といっています
gundetaにbolt_typeという指定があり
そこで銃のタイプごとに処理分けてる感じになります(クローズドボルトの銃は途中リロードで+1発の再現のためです
おそらく"close"と比較したいということですかね
gundetaのbolt_typeがcloseか比較したい感じです
bolt_typeは文字列ですから"close"と比較してください
=1つは代入です。2つか3つにしてください
次はこちらのエラーが出ました・・・
またsetDynamicPropertyに<ItemStack>を渡すことはできません
リロード処理用から普通のに戻す際はelse ifの繰り返しになるのでしょうか?
リロード処理用から普通のに戻す...というのがどこのどういうものなのか知らないので...
好きに実装してください
一旦アイテムを置き換えちゃうのでどこかに元のアイテムを保存しておかないといけないんですよね・・・
const itemstackを取った後プレイヤーのDPに保存してDPからデータを改修して・・・ってやろうとしたんですが・・・
DPにアイテムを直接保存することはできません。元のアイテムを完全に保存する必要があるのか、データさえ保存できればよいのか、などによっても対応は変わるかと思います
できれば元のアイテムを保存したいですね・・・
(カスタム機能実装予定のため)
すいません この後アルバイトがあるので7時まで戻れません… 回答ありがとうございました・・・
元のアイテムを完全に保存する方法ってありますか?(ご飯も食べて戻りました)
変数のまま保つか、チェストなどに保存する、ですかね
とかですね
パラメータという形で分離できるのであればitemstackとして保存する必要はないとは思います
パラメーターはitemstackdynamicplopatyですね・・・
であれば分離して保存して復元することも可能ですね
修正しましたが同じエラーですね・・・
reloadfinishというのはDPに格納できないオブジェクトですね
手に持ってるアイテムのIDをDPに保存したい場合はどうすればいいですかね・・・・
手に持ってるアイテムのIDをsetDynamicPropertyに渡してください
メインハンドのアイテムID取得は過去ログにあった気がするので見て確認してきます
既にアイテム自体はitemStackという変数に取得していそうですね
はい
const typeId = itemStack.typeId;
アイテムのIDの取得はこれでいいですか?
一応確認です
ItemStackクラスを使用して下さい
エラーのほうは修正しました
修正後はどうなりましたか
リロード処理用の銃に置き換わらないだけですね・・・
確認したところタイプミスあったのでそれだけ直しましたが・・・
今試してる最中です
エラーなし 動作なしですね・・
現在のコードです
setItemには<ItemStack>の形にしてから渡してください。そのためにnew ItemStack()を使用できます
なるほどです
new ItemStack(reloadgun)
って感じですか?
はい
ItemStackをimportしてください
new ItemStack(reloadgun)
の後にですか? それとも一番上にですか?
1番上です
プレイヤーからconstしてるitemstackは消す感じですか?
消しません
ItemStackの先頭は大文字です。itemStackと区別してください
またnew ItemStack()は生成した<ItemStack>を返すので返り値を変数に保持するか直接引数に渡すなどしてください。ただ書くだけでは無意味です
その時のselectedSlotをどこかに保持すればよいかと
const slot = player.selectedSlot;
みたいな感じですか?
はい。それをrunTimeout内で参照すれば良いと思いますいえまあやりたいように実装してください
inventory.container.setItem(damagingEntity.slot,itemStack);
こんな感じでいいでしょうか?
こうしたならslotは変数です。damagingEntityには生えていません
const reloadslot = damagingEntity.selectedSlot; でスロットを取って
inventory.container.setItem(reloadslot,itemStack); で置き換えればいい感じですか?
できました!
回答ありがとうございました!
またエラーとかわからないところ出たら質問すると思います・・・
こちらの機体の武装である機銃が自機に当たってしまうのですがどうすればよろしいでしょうか?(アイテム発射方式です)
自己解決しました
アップデートによりこちらのコードが動かなくなってしまいました
エラーには
[Scripting][error]-Plugin [puchineko guns 2 - 1.0.0] - [main.js] ran with error: [SyntaxError: Could not find export 'Vector' in module '@minecraft/server']
と出ています
#script-api message
Vectorは削除されました
mathを使う場合math自体をアドオン内に複製しないといけないですね
正規実装されていない が正しいかと
???
mathモジュールはアドオン自体に入れるためimport文だけで大丈夫です
こんな感じですか?
配置の仕方次第ですが基本的には'./math/index.js'になります
import { Vector }from "./math/index.js"
こうですか?
[Scripting][error]-Plugin [puchineko guns 2 - 1.0.0] - [main.js] ran with error: [ReferenceError: Module [math/index.js] not found. Native module error or file not found.]
このエラーが出ますね・・・
どのようにアドオン内に複製すればいいですか?
なるほど(元となるファイルがどこにあるのかわかってない)
何とか自力で複製してvector3インポートできましたがこちらのエラーが出てしまいますね・・・
minecraft-math.jsはmain.jsと同階層に複製してあってコードはこんな感じです
minecraft-math.jsのdefault exportは何になっていますか
まあそもそもdefault exportされているものはわざわざfromで名前を変える必要は無いんですけどね
コレ・・・ですか?
なんだこれ
リンクを貰えれば
”たしか”これですね・・
ダウンロードしたとこうろ覚えです・・・
元コードがcommonだから把握しずらいな
import mcmath from './minecraft-math.js'; // mcmathは好きな名前に```のようにインポートして、```js
mcmath.Vector3Utils.add(a, b)```のように使えます
わかりました
52行のif文で、setItemがelseの方の60行目にしかないせいかと
マルチプレイ時にほかプレイヤーが素手の時のみ[Scripting][error]-TypeError: cannot read property 'typeId' of undefined at <anonymous> (main.js:100)と出て銃のシステムが動作しません・・・
現在のコードです
if(gunData[itemStack.typeId]!=undefined){
になります
単純に装備していない時の処理がないからでは?
なるほど!
if(itemStack.typeId!=air){
こんな感じですか?
itemStackとundefinedを比較してください
.typeIdは不要ですか?
存在しない可能性があるので不要です
なるほどです
if(itemStack?.typeId!=undifined){
こういう場合なら問題ないという認識で大丈夫ですか?
はい
なるほどです
専用アイテムをオフハンドに持つと専用UIを開いて銃のカスタムをできるようにしたいのですが可能でしょうか?
イメージとしてはhttps://i.ytimg.com/vi/JXKN7Fg13EA/maxresdefault.jpg
のようなUIを開いてアイテムのDPに書き込んでカスタムをアイテムモデルに適用する感じです
(画像は拾い物です)
アプデ対応したのですがこのようなエラーをはいてしまいます
原因を教えて頂けないでしょうか?
自己解決しました
追加で質問なのですがインベントリ内に特定のアイテムを持っているときだけリロード処理を実行するというコードはどのようにすればいいのでしょうか?
やり方としては再起処理ですべてのスロット探査しかないのでしょうか?
再帰処理というよりは普通にforループだと思いますが、それはさておきインベントリ全てを調べてください
function hasItemInInventory(player, itemId) {
const { container } = player.getComponent('inventory');
for (let i = 0; i < container.size; i++) {
const item = container.getItem(i);
if (!item) continue;
if (item.typeId === itemId) return true;
}
return false;
}
プレイヤーのインベントリ内に指定したアイテムと同じものがあればtrueを返し、無かったらfalseを返すコードです
なにかしらエラーが出ましたらまた教えてください
hasItemInInventory関数を他で使わないのなら定義(function has...(...) { ... })を書く場所はそこでいいと思いますが、問題なのはすぐ下のifに書いてある関数の呼び出しです
関数を呼び出すときはfunction は書きません
呼び出し方はhasItemInInventory(damagingEntity, 'アイテムID')のような感じになるはずです
const OffhandEquipment = player.getComponent(mc.EntityComponentTypes.Equippable).getEquipment(mc.EquipmentSlot.Offhand);
オフハンドのアイテムは確かこれで取得できたはず
(mc.はないことに注意
なるほどです
多忙なためなかなか試せなくて結果だせず申し訳ありません
現在こちらのコードでエラーなし動作せずとなっております・・・・
何をする部分が動作していないのですか
モード切替・リロードの部分のfunction以下ですね・・
function hasItemInInventory(reloaditem) {この様に宣言してhasItemInInventory(damagingEntity, reloaditem)この様に呼び出すのはおかしいですね
というよりそもそも関数の実装が正しくない...どうしよう
まず関数の宣言自体はこれをそのまま使って良いです
これはplayerがitemIdの指すアイテムをインベントリに所持しているかを返す関数で、例えば以下のように使います
hasItemInInventory(damagingEntity, "minecraft:diamond")```
これはdamagingEntity(の指すプレイヤー)がダイヤモンドを持っているかをtrue/falseで返します
で、今行いたいことはdamagingEntityがリロードアイテム(const reloadgun = gunData[itemStack.typeId].reloadgun;の指すIDのアイテム)を持っているかを確認したいということでよいですかね
(data.js見てないからわからん
あ、ちなみに関数が何かわからない場合は調べてください
一応調べて見よう見まねでかいてみたのですが・・・
後はこのやりたいことをコードに落とすだけといえばだけです
変数いれるとこうなっちゃいますね・・・
凡ミスですね・・・
動作しました!
ありがとうございました!
projectile.shoot(velocity, { uncertainty: 10 });のようにuncertaintyの値を増やすとブレます、0だと全くブレずに飛んでいきます。
ありがとうございます
今夜試してみます(予定があるので今日夜まで試せません)
動作しました ありがとうございました!
dynamicplopatyを使ってアイテムのモデルを追加で表示することってできますか?
イメージとしては銃のモデルに追加でサイトなどのカスタムパーツ(別ファイル)を表示する感じです
イメージとしては旧ゲリラアドオンのカスタム機能をスプリクト化した感じです
※propertyです
attachablesから検出可能なものに変換さえしてやれば可能かとは思います
アニコン...とかでしょうか?
蓮根か
カスタムパーツのモデルと銃ごとの位置指定のアニメーションを用意してdynamicpropertyを検出してスプリクトでアニメーションを実行する・・・とかですかね?
残弾がない時でも発射アニメーションが実行されるバグ対策として残弾ゼロの際に発射アニメーションに移行しない銃に持ってるアイテムを変更するようにしたのですがモードや残弾等がundefinedになってしまいます
どのようにすればよろしいでしょうか?
(置き換え自体は動作しています)
分かっていたら何行目らへんの処理の何がundefinedなのかも書いてほしいです
リロード処理の残弾書き換え部分ですね
修正試みた結果がこれ出す
リロード演出用のアイテムに置き換えがうまくってないのと
残弾がundefinedになる感じですね
言葉で言われても探すのが大変なので具体的なコードや行数も教えてくださいという意味です
71から78行目です
inventory.container.setItem(damagingEntity.selectedSlotIndex,reload);//リロード用銃に置き換え
system.runTimeout(() => {
inventory.container.setItem(reloadslot,finishgun);
const itemStack = equipmentCompPlayer.getEquipment(reloadslot.Mainhand);
itemStack.setDynamicProperty("ammo", maxammo);
},reloadtime);
inventory.container.setItem(reloadslot,itemStack);
この辺が怪しいです
本来は演出用の銃に置き換えた後
アニメーション終了のタイミングで最大装弾数書き込んだ銃に置き換えてます
おそらくrunTimeout内で変更されたItemStackをsetしていないせいかと思われます
元のほうだとfinishgun、今書かれたものだとitemStackですかね
すいません78はタイプミスです
itemStack = new equipmentCompPlayer.getEquipment(EquipmentSlot.Mainhand);
こんな感じで大丈夫でしょうか?
というかnew…?
んーと
そこにおいてitemStackは42らへんで宣言されたconstのitemStackを参照します
constは再代入できないのでエラーになります
そしてnewというのはクラスやコンストラクタにつけて新たなオブジェクトを生成する演算子です
なんであるのか分かりませんが要りません
constを消すだけで大丈夫な感じですか?
変数宣言を理解してください
constを消したら宣言がなくなってしまいます
42のitemStackを上書きしてもいいならletを使ってもいいし、75で新たなitemStackの宣言をしても良いです
被りが嫌なら変数名を変えてください
なるほどです
このような形で別宣言を用意するのもいい感じですか?
また80から88行目のコードで本来ならこのような形でリロードアニメーション処理用の銃に置き換えているのですがこちらでは動作しません
どのようにすればいいですか?
弾薬のほうは動作したのですがまたアニメーションが動かなくなりました・・・
現状のファイルになります
自己解決しました
ありがとうございました
39行目のコードの書き方について教えてもらいたいです
やりたいことは射撃時に撃ったプレイヤーをソースにダメージを与えることと銃弾でプレイヤーをキルしたときに
キルしたプレイヤー名はキルされたプレイヤーを射殺した
とキルログを変更したいです
どのようにすればよろしいでしょうか?
projectileHitEntityの各種プロパティについて
sourceで投擲物を当てた本人であるエンティティを返します。
projectileには発射した投擲物エンティティ(銃弾のEntityID)等を返します
getEntityHitを使うと当てられたエンティティを返します。
イメージ
world.afterEvents.projectileHitEntity.subscribe((ev) => {
const { source, projectile } = ev;
const hitEntity = ev.getEntityHit.entity; //ヒットされたエンティティオブジェクトを返した分を参照するように宣言する。
const HP = hitEntity.getComponent('minecraft:health).currentValue;
if(HP < 0 && hitEntity.typeId == 'minecraft:player' && source.typeId === 'minecraft:player') {
world.sendMessage(`${hitEntity.name} は ${source.name} に射殺された。`);
//ヒットした時体力0になった、尚且つプレイヤーにやられたら発火するようにする。
}
});
私はこうしてます。
イメージはこんな感じなので、他の方だと多分全く違うかもしれません。
スマホで手打ちしてるので構文エラー出るかもしれません。
あとはキルログはバニラのものと独自のものが同時に出ますのでゲームルールで消すのもありです。
または、バニラのテキストを変えるならリソパの言語ファイル辺りになります。
回答ありがとうございます
バニラのキルログを銃のダメージの場合のみ消したいときはどうすればいいですか?
beforeeventから ev.cancel = true
というのは何とかわかったのですがキャンセルするために死亡時にログを出すイベントがわからないので質問させていただきました
すいません コード記述したところこのようなエラーが出るようになりました
どうすればいいでしょうか?
43行目のgetEntityHitはメソッドなのでev.getEntityHit().entityのようにする必要があります
https://learn.microsoft.com/ja-jp/minecraft/creator/scriptapi/minecraft/server/projectilehitentityafterevent?view=minecraft-bedrock-experimental#getentityhit
回答ありがとうございます!
32行目当たりのsource.getEquipmentですが、sourceはPlayerです。PlayerにはgetEquipmentというメソッドはありません。
他のところと同じようにEquippableコンポーネントを使ってください
これ以外にもミスがあるかまでは調べてないですが誤字などは丁寧に見直してみてください
()入れるの忘れてた、教えていたのにごめんなさい…
わかりました
プレイヤーのviewDirectionを任意の値増やしてapplyImpluseで与えてやれば良いかと
乗っているエンティティの取得はどうすればいいでしょうか?
回答ありがとうございます
しばらくの間多忙なので少し解答空くかと思いますがこれからもよろしくお願いします・・・
モジュールのタイプが"data"になっていますが、ScriptAPIを使用したいなら"script"である必要がありますよ
エラーは出ていますか
特に出ていないですね
DMで実際のアドオン送りましょうか?
(確かDMで送るのはよかったはず)
不要コード掃除したものになります
コード書きなおしたほうが早いですかね?
https://103.gigafile.nu/0511-437a635466102f3b76449d3498cb4c35
銃アドオンのバグ収めた映像です
このような形で連射が起きてしまいどのような改良を行ってもうまく作動しません
原因や修正方法等教えていだ焚けないでしょうか?
エラーログです
エラーを見て順番に潰していきましょう
アイテム関連のエラーを直したのですがまだ異常動作してますね・・・
アイテムへのDPの書き込みがうまく動いてないみたいです・・・
アイテムの使用をやめたって処理もうまく動いてないみたいです・・・
=マイクソ案件説出てきた
コードが謎いのでマイクソ案件ではないと思います...
もともと1.19.x系で書いたコードで1.20.x系になってから動かなくなってるんですよね・・・
まだ同じエラーが出てるんですか?
スプリクトのエラーは全解消したのですが1.20系アプデ前と動作順序が変わったのかこの動画のようになってしまいます
動画見れないですね...
再アップしました
動作順序が不安定なものに依存していた場合もあるので書き直した方が速いかもしれないです
(コードの全貌が見えづらいので何とも言えないです)
順番に実行したい場合ってどうすればいいですか?