Skip to content

Instantly share code, notes, and snippets.

@CherryDT
Created November 1, 2018 11:16
Show Gist options
  • Save CherryDT/421a17d9fae9df3f1f9ceec1e9b48976 to your computer and use it in GitHub Desktop.
Save CherryDT/421a17d9fae9df3f1f9ceec1e9b48976 to your computer and use it in GitHub Desktop.
DynRPG Keyboard & Mouse Input Plugin
/*
keyboard_mouse_input
A plugin for RPG Maker 2003
Using DynRPG - the RM2k3 Plugin SDK
This plugin allows you to read the mouse position and the status
of all keys.
By David "Cherry" Trapp
*/
#define AUTO_DLLMAIN
#include <DynRPG/DynRPG.h>
#include <sstream> // For std::stringstream
// We store the configuration in these variables
// It is much faster than accessing the std::map every time
int keySwitches[256];
int mouseXVar;
int mouseYVar;
// This handler is called on startup
bool onStartup(char *pluginName) {
// We load the configuration from the DynRPG.ini file here
std::map<std::string, std::string> configuration = RPG::loadConfiguration(pluginName);
// ...and extract the settings we need into our global variables
// First, the key switches
for(int i = 0; i < 256; i++) {
std::stringstream key;
key << "Key" << i << "Switch";
keySwitches[i] = atoi(configuration[key.str()].c_str()); // atoi is the easiest way here to get an integer
}
// And now the mouse variables
mouseXVar = atoi(configuration["MouseXVar"].c_str());
mouseYVar = atoi(configuration["MouseYVar"].c_str());
return true; // Don't forget to return true so that the start of the game will continue!
}
// This handler is called every frame
void onFrame(RPG::Scene scene) {
// Note: We won't check for invalid switch IDs, because writing to
// to them won't do anything at all anyway.
// First, we set all key switches to "OFF".
for(int i = 0; i < 256; i++) {
RPG::switches[keySwitches[i]] = false;
}
// Now, we turn those switches on whose associated key is pressed.
// This allows several keys to be bound to the same switch.
for(int i = 0; i < 256; i++) {
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms646293%28v=vs.85%29.aspx
if(GetAsyncKeyState(i) & 0x8000) {
RPG::switches[keySwitches[i]] = true;
}
}
// Now we get the mouse coordinates. That's a bit tricky, because in windowed
// mode there is a border (width: 2 pixels) around the "real" screen, and in the
// "large window mode" we have to take the fact into account that one pixel in the
// game is really 2x2 pixels on the real screen.
// So, first we get the position of the mouse, relative to the computer's screen.
POINT mousePos;
GetCursorPos(&mousePos);
// Then, we make this position relative to the "game screen window".
ScreenToClient(RPG::screen->getCanvasHWND(), &mousePos);
// If we are in windowed mode, we need to subtract 2 pixels from both X and Y
if(!RPG::screen->fullScreen) {
mousePos.x -= 2;
mousePos.y -= 2;
// And if we are in the large window mode, we need to divide the coordinates by 2
if(RPG::screen->largeWindow) {
mousePos.x /= 2;
mousePos.y /= 2;
}
}
// Now, we set the coordinates to the variables
RPG::variables[mouseXVar] = mousePos.x;
RPG::variables[mouseYVar] = mousePos.y;
// Finally, we need to update the event page start conditions because we changed
// switches and/or variables which may be start conditions at some event pages
RPG::map->updateEvents();
}
// This handler is called when an event comment was encountered
bool onComment(const char *text, const RPG::ParsedCommentData *parsedData,
RPG::EventScriptLine *nextScriptLine, RPG::EventScriptData *scriptData,
int eventId, int pageId, int lineId, int *nextLineId)
{
// First we check whether the "CheckKey" command was used.
// RPG::ParsedCommentData::command will always be in lower
// case, though, so we check for "checkkey".
if(strcmp(parsedData->command, "checkkey") == 0) {
// Next, we make sure that the parameters are valid
// (two numerical parameters).
// Parameter 0 is the key code, parameter 1 is the
// ID of the switch we should write the result to.
if(parsedData->parametersCount == 2 &&
parsedData->parameters[0].type == RPG::PARAM_NUMBER &&
parsedData->parameters[1].type == RPG::PARAM_NUMBER)
{
// We load the parameters to integers
int keyId = (int)parsedData->parameters[0].number;
int switchId = (int)parsedData->parameters[1].number;
// Now we check whether the key is pressed and set the
// switch accordingly.
if(GetAsyncKeyState(keyId) & 0x8000) {
RPG::switches[switchId] = true;
} else {
RPG::switches[switchId] = false;
}
} else {
// Show an error if the parameters were invalid
RPG::showError("Parameters invalid for CheckKey function!", eventId, pageId, lineId);
}
return false; // We handled this command, so we return false!
} else if(strcmp(parsedData->command, "checkallkeys") == 0) {
// Next, we make sure that the parameters are valid
// (one numerical parameter).
// Parameter 0 is the ID of the variable we should write
// the result to.
if(parsedData->parametersCount == 1 &&
parsedData->parameters[0].type == RPG::PARAM_NUMBER)
{
// We load the parameter to an integer
int variableId = (int)parsedData->parameters[0].number;
// We set the variable to zero first...
RPG::variables[variableId] = 0;
// ...then we check all keys (skipping 0 to 8 because
// they are actually mouse buttons)...
for(int i = 8; i < 256; i++) {
if(GetAsyncKeyState(i) & 0x8000) {
// ...and if a key is pressed, we set the
// variable to the key code and stop.
RPG::variables[variableId] = i;
break;
}
}
} else {
// Show an error if the parameters were invalid
RPG::showError("Parameters invalid for CheckAllKeys function!", eventId, pageId, lineId);
}
return false; // We handled this command, so we return false!
}
return true; // If we weren't able to handle the command, we return true!
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment