Post by Kamuna on Jun 12, 2014 12:23:12 GMT
Resources: dl.dropboxusercontent.com/u/176781620/Doppelganger%20Mode.zip
Now, you're ready for the next step in Mystery Script. By now you should know how to set things up, so I'll only be explaining anything that's new.
Doppelganger.ms:
Set up your mode and create necessary the files, which should be a piece of cake to you by now.
--------------------------------------------------------------------------------------------------------------------------------------------------
DoppelgangerStart.ms:
list_cycle("mob",GetAlive(),"see_invisible(my,1);"); - This is a list cycle. Get used to it, you're going to be seeing it a lot in advanced modes. The first argument is where it will search within all object's types for the text you place there. For example "mob" would include /mob/player, /mob/students, /mobilefakething/fakemobmob. Just searches for whatever has the letters mob in it in that order. Using that, it cycles through the list specified in the second arguement, in this case GetAlive(). Next, it runs the code located within the third argument with the variable my being the object in question. So, basically, what this does is searches for mob types in GetAlive(), which should be every in-round player at this point, then sets all of them to be able to see invisibility up to a level of one.
theshadow = hiddenoverlay(killer,customrole1,"doppelstudent.dmi"); - This sets a variable object named theshadow to a "hidden overlay" attached to the killer (1st argument), and shows it only to customrole1, which is the Eyes of Truth Holder (2nd argrument), that has the icon doppelstudent.dmi (3rd argument).
create_verb(killer,"Devour Corpse",file2text("DoppelPowers.ms"),"","Doppelganger"); - This creates a verb for the killer (1st arg), named Devour Corpse (2nd arg), that runs the code contained in DoppelPowers.ms (3rd arg), placed in the Doppelganger tab (4th arg).
create_verb(customrole1,"Activate/Deactivate Eyes of Truth",file2text("EyesPowers.ms"),"","Eyes of Truth"); - This creates a verb for customrole1 named Activate/Deactivate Eyes of Truth that runs the code contained in EyesPowers.ms placed in the Eyes of Truth tab.
see_invisible(customrole1,0); - Customrole1 (Eyes of Truth), by default, cannot see the Doppelganger's fake form (student form), therefore there is no reason to have them see it under the true form (theshadow).
---------------------------------------------------------------------------------------------------------------------------------------------------
invisibility(killer,1); - Sets the invisibility level of the killer to 1.
invisibility_interactivity(killer,1); - Allows other players that cannot see the killer to interact directly with the killer, i.e push them.
--------------------------------------------------------------------------------------------------------------------------------------------------
Next is the main loop. It uses checks mstags to toggle customrole1's ability to see the killer's student form or theshadow. It deletes theshadow when the eyes are off and theshadow exists (and resets it to 0 to make any if statements referring to it false) and allows customrole1 to see the killer (the fake form). Else, it does the opposite, creates theshadow when it doesn't exist and disables the ability for customrole1 to see the killer. Outside of the loop (end of the game), it makes sure that the killer's invisibility and interactivity is reset, as well as customrole1's ability to see invisible things, so those don't carry over to the next round.
--------------------------------------------------------------------------------------------------------------------------------------------------
DoppelPowers.ms:
X = list(); - Makes an empty list named X
list_cycle("corpse",view(1,killer),"set_mstag(my,\"Check!\");"); - Sets the mstag of all corpses within 1 tile of the killer to Check!
while(find_mstag("Check!") && gameinprogress)
{
gameinprogress = gameinprogress();
addlist(X,find_mstag("Check!"));
set_mstag(find_mstag("Check!"),"");
} - find_mstag returns the first entity that it finds with that mstag. This while loop loops through everything with the mstag "Check!", adds them to the list X, and sets the mstag back to nothing ("")
Y = 0; - Set Y to 0, just in case there is no dialogue.
Y = dialogue(killer,"What do you wish to devour?","Devour",X); - Sets up a dialogue box in which it asks the killer "What do you wish to devour?", with the title "Devour", showing them the list X which we made previously. Returns the chosen value/object.
if(Y) -If Y exists
{
if(findinlist(killer,GetAlive()))
{
if(findinlist(Y,view(1,killer)))
{
if(istype(Y,"/obj/containers/corpse")) - Makes sure Y is a corpse
{
printto(killer,"You devour the corpse and switch bodies.");
corpseicon = get_icon(Y); - All of these below are self explanatory
killericon = get_icon(killer);
killergender = get_RPgender(killer); - RPGender is the player's ingame gender (only male/female), while gender/realgender is the player's actual set gender, which includes neuter.
corpsealias = get_alias(Y);
killeralias = get_alias(killer);
corpsegender = get_realgender(Y); - Since corpses don't have RPgenders (the player's RPgender carries to their realgender), we gather the realgender from the corpse.
set_name(killer,corpsealias);
set_alias(killer,corpsealias);
set_icon(killer,corpseicon);
set_RPgender(killer,corpsegender);
set_name(Y,strcat(killeralias,"'s dead body"));
set_alias(Y,killeralias);
set_icon(Y,killericon);
set_iconstate(Y,"dead");
set_realgender(Y,killergender);
}
}
}
}
}
----------------------------------------------------------------------------------------------------------------------------------------------------
EyesPowers.ms:
Nothing new here, changes the mstags of customrole1 and sends a message to the player.
---------------------------------------------------------------------------------------------------------------------------------------------------
DoppelgangerEnd.ms:
Typical End Game Code, but I must note that strcat now takes multiple arguments, so all those variables at the beginning aren't necessary anymore.
----------------------------------------------------------------------------------------------------------------------------------------------------
We have successfully created Doppelganger Mode, congrats! Now you are a full-fledged Mystery Scripter. Be proud!
Now, you're ready for the next step in Mystery Script. By now you should know how to set things up, so I'll only be explaining anything that's new.
Doppelganger.ms:
setkiller("Doppelganger");
setcustomrole1("Eyes of Truth");
setcustommode("Doppelganger",2,"http://misuteriihigh.boards.net/thread/142/tutorial-creating-doppelganger-mode-advanced","Doppelganger.ogg","Doppelganger.dmi",file2text("DoppelgangerStart.ms"),file2text("DoppelgangerEnd.ms"),2);
Set up your mode and create necessary the files, which should be a piece of cake to you by now.
--------------------------------------------------------------------------------------------------------------------------------------------------
DoppelgangerStart.ms:
wprint("<big><font color=red><b>Warning:</b></font> Dead body located on the premises. Simple program analysis highly suggests either murder or assisted suicide; saving video feed from just before the event. Facility has been locked down until This System's authorities can be reached.</big>");
showkiller("You are the Doppelganger!");
printto(killer,"<b><i>You are the Doppelganger!</i></b>");
printto(killer,"<i>In order to tame your hunger, you've devoured one of the teachers' souls. You left her body in the courtyard and made a mad dash to wash the evidence away. However, you've been caught out by the school security system and now you're trapped with a whole bunch of other students. Now you hunger again and your only option is to trick and devour the students with your transformation powers.</i>");
printto(customrole1,"<b><i>You have the Eyes of Truth!</i></b>");
showcustomrole1("You have the Eyes of Truth!");
printto(customrole1,"Ever since you were little, you were able to see The Truth. Now that there's a murderer on the loose, you should probably use those eyes to protect yourself somehow! You should probably not touch suspicious entities much, though...");
list_cycle("mob",GetAlive(),"see_invisible(my,1);");
theshadow = hiddenoverlay(killer,customrole1,"doppelstudent.dmi");
create_verb(killer,"Devour Corpse",file2text("DoppelPowers.ms"),"","Doppelganger");
create_verb(customrole1,"Activate/Deactivate Eyes of Truth",file2text("EyesPowers.ms"),"","Eyes of Truth");
see_invisible(customrole1,0);
gameinprogress = gameinprogress();
while(gameinprogress)
{
gameinprogress = gameinprogress();
if(gameinprogress)
{
if(findinlist(killer,GetAlive()))
{
invisibility(killer,1);
invisibility_interactivity(killer,1);
list_cycle("mob",GetAlive(),"if(my != customrole1){see_invisible(my,1);wait(tick_lag());}");
roletag = check_mstag(customrole1);
if(findinlist(customrole1,GetAlive()))
{
if(roletag != "Eyes Off")
{
see_invisible(customrole1,0);
}
else
{
see_invisible(customrole1,1);
}
}
}
if(findinlist(customrole1,GetAlive()))
{
roletag = check_mstag(customrole1);
if(roletag != "Eyes Off")
{
if(!theshadow)
{
theshadow = hiddenoverlay(killer,customrole1,"doppelstudent.dmi");
see_invisible(customrole1,0);
}
}
if(roletag == "Eyes Off")
{
if(theshadow)
{
ent_delete(theshadow);
theshadow = 0;
see_invisible(customrole1,1);
}
}
}
else
{
if(findinlist(customrole1,GetWatcher()))
{
see_invisible(customrole1,2);
}
}
}
wait(10);
}
invisibility(killer,0);
invisibility_interactivity(killer,0);
see_invisible(customrole1,0);
list_cycle("mob",GetAlive(),"see_invisible(my,1);"); - This is a list cycle. Get used to it, you're going to be seeing it a lot in advanced modes. The first argument is where it will search within all object's types for the text you place there. For example "mob" would include /mob/player, /mob/students, /mobilefakething/fakemobmob. Just searches for whatever has the letters mob in it in that order. Using that, it cycles through the list specified in the second arguement, in this case GetAlive(). Next, it runs the code located within the third argument with the variable my being the object in question. So, basically, what this does is searches for mob types in GetAlive(), which should be every in-round player at this point, then sets all of them to be able to see invisibility up to a level of one.
theshadow = hiddenoverlay(killer,customrole1,"doppelstudent.dmi"); - This sets a variable object named theshadow to a "hidden overlay" attached to the killer (1st argument), and shows it only to customrole1, which is the Eyes of Truth Holder (2nd argrument), that has the icon doppelstudent.dmi (3rd argument).
create_verb(killer,"Devour Corpse",file2text("DoppelPowers.ms"),"","Doppelganger"); - This creates a verb for the killer (1st arg), named Devour Corpse (2nd arg), that runs the code contained in DoppelPowers.ms (3rd arg), placed in the Doppelganger tab (4th arg).
create_verb(customrole1,"Activate/Deactivate Eyes of Truth",file2text("EyesPowers.ms"),"","Eyes of Truth"); - This creates a verb for customrole1 named Activate/Deactivate Eyes of Truth that runs the code contained in EyesPowers.ms placed in the Eyes of Truth tab.
see_invisible(customrole1,0); - Customrole1 (Eyes of Truth), by default, cannot see the Doppelganger's fake form (student form), therefore there is no reason to have them see it under the true form (theshadow).
---------------------------------------------------------------------------------------------------------------------------------------------------
invisibility(killer,1); - Sets the invisibility level of the killer to 1.
invisibility_interactivity(killer,1); - Allows other players that cannot see the killer to interact directly with the killer, i.e push them.
--------------------------------------------------------------------------------------------------------------------------------------------------
Next is the main loop. It uses checks mstags to toggle customrole1's ability to see the killer's student form or theshadow. It deletes theshadow when the eyes are off and theshadow exists (and resets it to 0 to make any if statements referring to it false) and allows customrole1 to see the killer (the fake form). Else, it does the opposite, creates theshadow when it doesn't exist and disables the ability for customrole1 to see the killer. Outside of the loop (end of the game), it makes sure that the killer's invisibility and interactivity is reset, as well as customrole1's ability to see invisible things, so those don't carry over to the next round.
--------------------------------------------------------------------------------------------------------------------------------------------------
DoppelPowers.ms:
if(findinlist(killer,GetAlive()))
{
X = list();
list_cycle("corpse",view(1,killer),"set_mstag(my,\"Check!\");");
gameinprogress = gameinprogress();
while(find_mstag("Check!") && gameinprogress)
{
gameinprogress = gameinprogress();
addlist(X,find_mstag("Check!"));
set_mstag(find_mstag("Check!"),"");
}
Y = 0;
Y = dialogue(killer,"What do you wish to devour?","Devour",X);
if(Y)
{
if(findinlist(killer,GetAlive()))
{
if(findinlist(Y,view(1,killer)))
{
if(istype(Y,"/obj/containers/corpse"))
{
printto(killer,"You devour the corpse and switch bodies.");
corpseicon = get_icon(Y);
killericon = get_icon(killer);
killergender = get_RPgender(killer);
corpsealias = get_alias(Y);
killeralias = get_alias(killer);
corpsegender = get_realgender(Y);
set_name(killer,corpsealias);
set_alias(killer,corpsealias);
set_icon(killer,corpseicon);
set_RPgender(killer,corpsegender);
set_name(Y,strcat(killeralias,"'s dead body"));
set_alias(Y,killeralias);
set_icon(Y,killericon);
set_iconstate(Y,"dead");
set_realgender(Y,killergender);
}
}
}
}
}
X = list(); - Makes an empty list named X
list_cycle("corpse",view(1,killer),"set_mstag(my,\"Check!\");"); - Sets the mstag of all corpses within 1 tile of the killer to Check!
while(find_mstag("Check!") && gameinprogress)
{
gameinprogress = gameinprogress();
addlist(X,find_mstag("Check!"));
set_mstag(find_mstag("Check!"),"");
} - find_mstag returns the first entity that it finds with that mstag. This while loop loops through everything with the mstag "Check!", adds them to the list X, and sets the mstag back to nothing ("")
Y = 0; - Set Y to 0, just in case there is no dialogue.
Y = dialogue(killer,"What do you wish to devour?","Devour",X); - Sets up a dialogue box in which it asks the killer "What do you wish to devour?", with the title "Devour", showing them the list X which we made previously. Returns the chosen value/object.
if(Y) -If Y exists
{
if(findinlist(killer,GetAlive()))
{
if(findinlist(Y,view(1,killer)))
{
if(istype(Y,"/obj/containers/corpse")) - Makes sure Y is a corpse
{
printto(killer,"You devour the corpse and switch bodies.");
corpseicon = get_icon(Y); - All of these below are self explanatory
killericon = get_icon(killer);
killergender = get_RPgender(killer); - RPGender is the player's ingame gender (only male/female), while gender/realgender is the player's actual set gender, which includes neuter.
corpsealias = get_alias(Y);
killeralias = get_alias(killer);
corpsegender = get_realgender(Y); - Since corpses don't have RPgenders (the player's RPgender carries to their realgender), we gather the realgender from the corpse.
set_name(killer,corpsealias);
set_alias(killer,corpsealias);
set_icon(killer,corpseicon);
set_RPgender(killer,corpsegender);
set_name(Y,strcat(killeralias,"'s dead body"));
set_alias(Y,killeralias);
set_icon(Y,killericon);
set_iconstate(Y,"dead");
set_realgender(Y,killergender);
}
}
}
}
}
----------------------------------------------------------------------------------------------------------------------------------------------------
EyesPowers.ms:
roletag = check_mstag(customrole1);
if(roletag == "Eyes Off")
{
if(findinlist(customrole1,GetAlive()))
{
set_mstag(customrole1,"");
printto(customrole1, "Eyes of Truth Activated.");
}
}
else{
if(findinlist(customrole1,GetAlive()))
{
set_mstag(customrole1,"Eyes Off");
printto(customrole1, "Eyes of Truth Deactivated.");
}
}
Nothing new here, changes the mstags of customrole1 and sends a message to the player.
---------------------------------------------------------------------------------------------------------------------------------------------------
DoppelgangerEnd.ms:
a = strcat("The Doppelganger was ",get_realname(killer));
b = strcat(" / ",get_permalias(killer));
c = strcat(", played by ",get_key(killer));
d = strcat(a,b);
e = strcat(d,c);
wprint(e);
wait(3);
k = strcat("The Eyes of Truth was ",get_realname(customrole1));
l = strcat(" / ",get_permalias(customrole1));
m = strcat(", played by ",get_key(customrole1));
n = strcat(k,l);
o = strcat(n,m);
wprint(o);
wait(3);
numdead = length(GetDead());
numalive = length(GetAlive());
if(numdead > 0)
{
if(numalive < 1)
{
wprint("Everyone has met death. What an unfortunate end.");
}
if(numalive == 1)
{
if(!findinlist(killer,GetAlive()))
{
wprint("One lucky student has survived the onslaught.");
}
else
{
wprint("The Doppelganger has taken over the school. Only one remains.");
}
}
if(numalive > 1)
{
if(!findinlist(killer,GetAlive()))
{
wprint("The Doppelganger's onslaught has failed.");
}
else
{
wprint("Some people lived and some people died. The Doppelganger, however, lives to devour another day.");
}
}
}
else
{
wprint("It seems that nobody died. What was the Doppelganger thinking?");
}
Typical End Game Code, but I must note that strcat now takes multiple arguments, so all those variables at the beginning aren't necessary anymore.
----------------------------------------------------------------------------------------------------------------------------------------------------
We have successfully created Doppelganger Mode, congrats! Now you are a full-fledged Mystery Scripter. Be proud!