How i knockback a player near of Player ? i want to make an shield. With PlayerItemHeldEvent or PlayerInteractEvent
I would recommend learning php first(if you have not) and if you have what specific questions do you have on how to do this because I'm not going to spoon feed you all of the code
You arent new to PHP you know it and I know it and you know me we made 8 months ago a plugin together and you made a part and I! Dont lie to us...
Ok this is intresting so lets make it simple the event handler can be forgotten(since it is easily replacable) we just need to know how to caculate a knock back motion and apply it to players in range of the knock back ev trigger example the trigger is /knockbackall so how do we do that the only thing i don't get is setting the motion getting range is easy and so does the players so foreach palyers as player player -> setmotion (something???) assuming the code should be somewhere inside class Explosion
PHP: public function knockbackCheck($pl){foreach($pl->getLevel()->getPlayers() as $p){if($p->distanceSquared($pl) == pow(5, 2)){$p->setMotion(new Vector3($p->x - $pl->x, $p->y - $pl->y, $p->z - $pl->z));}}} Call knockbackCheck() in a task and use the player you want to protect as the first parameter.
There are two ways: The first one is hard. When a player is in the knockback radius of a player, atan2() will be called and the coordinates are the players coordinates subtracted by the coordinates of the knockback player. Then convert the radians to degrees with rad2deg(). After it's done we need a second formula: PHP: $yaw *= M_PI / 180; // turn into radians, you can use deg2rad() too$x = cos($yaw);$z = sin($yaw);$pl->setMotion(new Vector3(-$x, 1, -$z)); This uses atan2(), a formula to get the yaw to look at an object as example. And cos() which is used by the MCPE devs to let entities move to where they look at, I added a minus in front of the variable because they are supposed fall back. The second way is simply subtracting the player's coordinates with the coordinates of the entity, and use it as motion.
I'd recommend you this code: PHP: public function knockbackCheck($pl){foreach($pl->getLevel()->getPlayers() as $p){if(($dist = root($p->distanceSquared($pl))) == 5){$dir = $pl->subtract($p);$dir = $dir->divide($dist);$yaw = atan2(-$dir->getX(),$dir->getZ());$x = cos($yaw);$z = sin($yaw);$p->setMotion(new Vector3(-$x, 1, -$z));}}}
but don't that knock everyone regardless of range? and pitch is not defined? also what about the get yaw function inside player
same with $dist idk what he was doing there but would getNearByEntities(or something like that not sure) work in this situation haven't looked at it much at all been meaning to
Why are you using Entity::setMotion()? There exists such a thing as Living::knockBack() which would work better in this situation. The best way to go about this is listening to player move event and detect when a player walks into another players 'force field'. This will reduce the delay on the knock back to the intruding player due to being able to cancel the actual movement and knocking the player back instead. I would do something like this: PHP: public function onMove(pocketmine\event\player\PlayerMoveEvent $event) { $player = $event->getPlayer(); foreach($player->getViewers() as $viewer) { // continue the loop if the player is more than 5 blocks away if($player->distance($viewer) > 5) continue; // Check the item in the players hand to see if it is the 'force field' item if($viewer->getItemInHand()->getId() === pocketmine\item\Item::STICK) { // knock the moving player back if there is a force field $player->knockBack($viewer, 0, $player->x - $viewer->x, $player->z - $viewer->z, 0.4); // Break the loop so the player doesn't get knocked back multiple times from one movement break; } }}
Just saying you won't learn anything without trying :/ PHP: <?phpnamespace xbeastmode\shield;use pocketmine\Player;use pocketmine\event\Listener;use pocketmine\event\player\PlayerMoveEvent;use pocketmine\math\AxisAlignedBB;class EventListener implements Listener{ /** * @param PlayerInteractEvent $e */ public function onInteract(PlayerMoveEvent $e){ //if player has shield $r = 15;//radius of shield foreach ($e->getPlayer()->getLevel()->getNearbyEntities(new AxisAlignedBB($p->x-$r, $p->y-$r, $p->z-$r, $p->x+$r, $p->y+$r, $p->z+$r)) as $player) {//get all entities within radius of the shield if($entity instaceof Player){//if entity is player //now you can use variable $player to knock them back or do your own thing } } }}
pow() accepts two parameters. Also try using the ** operator added in PHP 5.6. What's your logic? The further players away, the more knockback?
Work this? PHP: public function onItemHeld(PlayerItemHeldEvent $event){ $player = $event->getPlayer(); $iteminhand = $player->getInventory()->getItemInHand(); $itemid = $event->getItem()->getId(); $config = $this->getConfig(); $lobby = $config->get('Lobby'); $lobby2 = $config->get('Lobby2'); if($player->getLevel()->getName() == $lobby or $lobby2){ switch($itemid){ case 330; $r = 7; foreach($player->getLevel()->getNearbyEntities(new AxisAlignedBB($p->x-$r, $p->y-$r, $p->z-$r, $p->x+$r, $p->y+$r, $p->z+$r)) as $players){ if($players instanceof Player){ $player->knockBack($player, 1.0); } } } }