본문 바로가기
마인크래프트/Skript 기초 활용편

스크립트 기초 활용 3편(상점 ver.1.0)

by 스터디립트 2022. 2. 21.

 

스터디립트의 마인크래프트 스크립트 기초 활용편의 3번째 시간입니다.

이번 시간에는 상점 스크립트에 대해서 알려드리겠습니다.

 

제목에 "상점 ver.1.0" 이라고 쓰여져 있는 것에 대해 궁금하신 분이 계실텐데요, 구매 부분만 간단하게 넣은 스크립트가 ver.1.0, 판매 부분까지 넣은 상점은 ver.2.0 으로 나눠서 알려드릴 예정입니다.

 

 

 

오늘은 구매 부분, 즉 ver.1.0에 대해서만 알려드리고, 판매 부분에 대해서는 추후에 알려드리도록 하겠습니다.

 

우선 설명해드리기에 앞서, 이 스크립트는 에센셜 플러그인, 시티즌 플러그인, 호환 플러그인(vault), SkQuery, SkChoke 애드온이 필요합니다.

 

참고로 저는 paper 버킷을 사용하고 있기에, 스피갓에 호환되는 플러그인, 버킷에 호환되는 플러그인을 섞어서 사용이 가능해서 상관 없이 쓰고있습니다. 여러분들은 자신의 서버 구동기에 맞춰 가려서 다운받으시길 바랍니다. 아래 주소들은 제가 다운로드 받은 사이트들 입니다.

 

↓ SkQuery 애드온

Addon - SkQuery [1.9-1.16+]

https://forums.skunity.com/resources/skquery-1-9-1-15.68/

 

 

↓ SkChoke 애드온

https://www.spigotmc.org/resources/skchoke.70314/

 

 

↓ 호환 플러그인

https://dev.bukkit.org/projects/vault

 

 

↓ 시티즌 플러그인

https://dev.bukkit.org/projects/citizens

 

 

↓ 에센셜 플러그인

https://dev.bukkit.org/projects/essentialsx

 

 

우선 구문을 설명드리기에 앞서서 스크립트를 사용하는 모습을 먼저 보시죠.

 

 
npc 소환

시티즌 플러그인에서

/npc create 테스트

를 사용해서 테스트란 이름의 npc를 만들었습니다.

 

상점 스크립트 도움말

완전하지 않은 명령어를 입력하였을 경우에는, 위 사진과 같이 도움말이 출력됩니다./상점 추가 상점 테스트를 통해서 테스트란 이름의 상점을 만들었습니다.

상점에 추가하고 싶은 아이템을 손에 든 후에,/상점 추가 아이템 테스트 1000을 통해서 테스트라는 이름의 상점은 이제 손에 들고있던 아이템을 1000원에 판매하게 됩니다.

 
 
상점 스크립트 사용 예시

 위 사진은 상점에 1000원짜리 눈을 추가한 모습입니다.

좌클릭을 통해서 아이템을 1개 구매할 수 있으며

shift + 좌클릭을 통해서 한 세트를 구매할 수 있습니다.

 

다만 돈이 없으면 살 수 없어야 하겠죠?

돈 시스템도 스크립트로 자체적으로 만들수야 있겠지만, 에센셜 플러그인만큼이나 간편하고, 다양하게 만들기는 어렵습니다.

 

 

또한, 이미 서버가 에센셜 플러그인을 사용하고 있다면 굳이 그 시스템을 갈아 엎고 스크립트로 새로 만들 필요성도 없죠.

 

따라서 에센셜 플러그인을 사용하는 것이고, 에센셜 플러그인과 스크립트를 호환시켜줄 vault 플러그인도 필요합니다.

 

/eco give [플레이어 이름] [액수] 를 통해서 에센셜 플러그인에서 플레이어에게 돈을 지급할 수 있습니다.

 

 

상점 스크립트 돈이 부족할 시
위 사진은 돈이 충분하지 않을 때 물건을 사려고 하면 출력되는 메시지입니다.

자 이렇게 상점 스크립트의 사용방법에 대해서 알아보았습니다..

 

 

이제 구문을 한번 살펴보겠습니다.

 

 

options:
	s : &2&l[&3&l상점&2&l]

command /상점 [<text>] [<text>] [<text>] [<integer>]:
    trigger:
        if player is op:
            if arg 1 is "추가" or "삭제" or "목록":
                if arg 1 is "추가":
                    if arg 2 is "상점" or "아이템":
                        if arg 2 is "상점":
                            if {상점목록::*} contains arg 3:
                                send "{@s} %arg 3%&2&l은 이미 있는 상점입니다"
                            else:
                                if arg 3 is set:
                                    add arg 3 to {상점목록::*}
                                    send "{@s} 상점목록에 %arg 3%&2&l(이)가 추가되었습니다"
                                else:
                                    send "{@s} 상점의 이름을 설정해 주세요"
                        if arg 2 is "아이템":
                            if {상점목록::*} contains arg 3:
                                if arg 4 is set:
                                    if player's tool is not air:
                                        if {상점.%arg 3%.진품::*} contains player's tool:
                                            send "{@s} 이 아이템은 이미 이 상점에서 거래중인 물건입니다"
                                        else:
                                            set {_product} to player's tool
                                            add {_product} to {상점.%arg 3%.진품::*}
                                            add " " to {_product}'s lore
                                            add "&4&l[ &f&l구매가격 &4&l]&r %arg 4%원" to {_product}'s lore
                                            add "&e&l[ &f&l좌클릭 &e&l]&r 구매" to {_product}'s lore
                                            add "&e&l[ &f&lShift+좌클릭 &e&l]&r 64개 구매" to {_product}'s lore
                                            add "&7##상품" to {_product}'s lore
                                            add {_product} to {상점.%arg 3%::*}
                                            send "{@s} 아이템이 %arg 3%&2&l에 추가되었습니다"
                                    else:
                                        send "{@s} 팔 물건을 들어주세요"
                                else:
                                    send "{@s} 구매가격을 설정해 주세요"
                            else:
                                send "{@s} 상점 %arg 3%&2&l은 존재하지 않는 상점입니다"
                    else:
                        send "&4[ &f사용방법 &4]"
                        send "&4[ &f/상점 추가 [상점/아이템] [상점이름] (구매가격) &4]"
                if arg 1 is "삭제":
                    if arg 2 is set:
                        if {상점목록::*} contains arg 2:
                            subtract arg 2 from {상점목록::*}
                            delete {상점.%arg 2%.진품::*}
                            delete {상점.%arg 2%::*}
                            send "{@s} %arg 2%&2&l(이)가 상점목록에서 삭제되었습니다"
                        else:
                            send "{@s} %arg 2%&2&l(은)는 존재하지 않는 상점입니다"
                    else:
                        send "&4[ &f사용방법 &4]"
                        send "&4[ &f/상점 삭제 [상점이름] &4]"
                if arg 1 is "목록":
                    if arg 2 is "상점" or "아이템":
                        if arg 2 is "상점":
                            send "&e&l&m---------------------------"
                            loop {상점목록::*}:
                                send "&e&l%{상점목록::%loop-index%}%"
                            send "&e&l&m---------------------------"
                        if arg 2 is "아이템":
                            if {상점목록::*} contains arg 3:
                                send "&e&l&m---------------------------"
                                loop {상점.%arg 3%.진품::*}:
                                    send "&e&l%{상점.%arg 3%.진품::%loop-index%}%"
                                send "&e&l&m---------------------------"
                            else:
                                if arg 3 is not set:
                                    send "{@s} 상점이름을 입력해 주세요"
                                else:
                                    send "{@s} %arg 3%&2&l은 존재하지 않는 상점입니다"
                    else:
                        send "&4[ &f사용방법 &4]"
                        send "&4[ &f/상점 목록 [상점/아이템] (상점이름) &4]"
            else:
                send "&4[ &f사용방법 &4]"
                send "&4[ &f/상점 추가 [상점/아이템] [상점이름] (구매가격) &4]"
                send "&4[ &f/상점 삭제 [상점이름] &4]"
                send "&4[ &f/상점 목록 [상점/아이템] (상점이름) &4]"
        else:
            send "{@s} 당신은 오피가 아니기에 이 명령어를 사용할 수 없습니다"

on rightclick on entity:
    if {상점목록::*} contains entity's name:
        open chest with 6 rows named "상점 %entity's name%" to player
        set {_count} to 0
        loop {상점.%entity's name%::*}:
            set slot {_count} of current inventory of player to loop-value
            add 1 to {_count}

on inventory click:
    if clicked slot > -1:
        if name of player's current inventory contains "상점":
            cancel event
            if click item is not air:
                set {_lore::*} to uncolored lore of click item
                loop {_lore::*}:
                     if {_lore::%loop-index%} contains "구매가격":
                        set {_buy} to {_lore::%loop-index%}
                        replace all " " and "[" and "]" and "구매가격" and "원" with "" in {_buy}
                        set {_buy} to {_buy} parsed as integer
                    if {_lore::%loop-index%} contains "##상품":
                        set {_name} to name of player's current inventory
                        replace all "상점 " with "" in {_name}
                        set {_products} to {상점.%{_name}%.진품::%clicked slot+1%}
                        if "%click type%" contains "LEFT":
                            if "%click type%" contains "SHIFT":
                                if player's money/64 >= {_buy}:
                                    subtract {_buy}*64 from player's money
                                    give 64 of {_products} to player
                                    send "{@s} 구매가 완료되었습니다"
                                else:
                                    send "{@s} 돈이 부족합니다"
                            else:
                                if player's money >= {_buy}:
                                    subtract {_buy} from player's money
                                    give 1 of {_products} to player
                                    send "{@s} 구매가 완료되었습니다"
                                else:
                                    send "{@s} 돈이 부족합니다"

원리는 저번 가방스크립트와 비슷합니다.

 

 

우선 손에 든 아이템을 {상점.%arg 3%.진품::*} 이라는 배열변수에 저장합니다.

그리고, {상점.%arg 3%::*} 라는 배열변수에 처음에 저장했던 아이템의 설명에 가격, 설명 등을 넣은 상태로 저장합니다.

그리고 npc를 우클릭했을때, npc의 이름이 상점 목록에 있는지를 판단하고, 만약 있다면 GUI창을 열고 {상점.%arg 3%::*} 에 저장했던 아이템들을 불러옵니다.

 

그리고 그 아이템을 클릭했을때, 아이템의 설명에 있는 가격에 맞추어 구매하는 방식입니다.

 

그러면 이제 구문을 알아보겠습니다.

 

if "%click type%" contains "LEFT":

 

이 구문은, 마우스의 왼쪽 버튼이 클릭되었는가? 라는 판단문입니다.

LEFT 대신에 SHIFT를 써서 64개 구매에 사용하기도 했죠.

 

if player's money >= {_buy}:

 

이 구문은, 플레이어가 소지하고 있는 돈이 {_buy} 라는 변수의 값보다 같거나 높은가? 라는 판단문입니다. {_buy} 라는 변수는 여러 과정을 통해 물건의 가격으로 설정되었습니다. 이 player's money 라는 것은, 에센셜 플러그인의 돈 시스템이 있어야지 사용이 가능합니다. 물론 스크립트로 에센셜 플러그인의 돈 시스템을 구현해서 사용하셔도 됩니다. 그리고, 호환 플러그인이 있어야지 player's money가 정상적으로 작동이 되기에 호환 플러그인도 필요합니다.

 

 

아래의 파일들은, 상점 스크립트 입니다.

주석이 있는 파일은 모든 강좌가 끝난 뒤에 천천히 올릴 예정입니다.

 

↓ 상점 스크립트 (주석없음)

상점.sk
0.01MB

↓ 상점 스크립트 (주석있음)

상점(주석 포함).sk
0.01MB

 

스터디립트의 마인크래프트 스크립트 기초 활용편 3편은 여기서 끝입니다.

다음 시간에는, 명령어의 사용을 금지하는 스크립트에 대해 알려드리겠습니다

질문이 있으시다면 이 글의 댓글 또는 질문카테고리 게시글의 댓글에 적어주시면 최대한 답변해드리겠습니다.

 

 

댓글